home *** CD-ROM | disk | FTP | other *** search
/ PC-Blue - MS DOS Public Domain Library / PC-Blue MS-DOS Public Domain Library - NYACC.iso / vol248 / tutorial.asc < prev    next >
Encoding:
Text File  |  1986-12-01  |  106.5 KB  |  2,641 lines

  1.  
  2.  
  3.  
  4.                 A Brief Course in Advanced Lotus 1-2-3 Functions
  5.  
  6.   1) Part I
  7.  
  8.        There are plenty of references where one can turn to learn the basics  of 
  9.   spreadsheets,  but  very  few  teaches the advanced features  of  the  various 
  10.   programs, and the user is often left to discover them by him (her) self.
  11.  
  12.        In  this series of short courses,  the less used,  and often very  useful 
  13.   functions  of  1-2-3  will be discussed.  These are functions that  makes  the 
  14.   difference between a ho-hum spreadsheet, and a great and fun tool to use.
  15.  
  16.        We will cover the macro capabilities,  the creation of menus, and finally 
  17.   the word-processing function of 1-2-3,  which are barely referred to,  and yet 
  18.   can be quite convenient.
  19.  
  20.        The  only knowledge that is assumed for this tutorial is that the  reader 
  21.   is able to move in the worksheet,  copy ranges,  erase ranges,  and other very 
  22.   basic procedure.
  23.  
  24.        Since  it  is  easier  to  demonstrate  the  different  function  through 
  25.   examples,  we will construct a hypothetical worksheet. For a change, this will 
  26.   not  deal  with the best way to invest your money,  sell stocks and  bond,  or 
  27.   other  financial  applications.  Instead  we will  use  a  medically  flavored 
  28.   problem. 
  29.  
  30.        As  you  know  there has been a strong tendency in Europe,  and  in  this 
  31.   country,  to  monitor  the evolution of the pregnancy  with  ultrasound.  This 
  32.   technique  allow to see the baby in its mother's uterus and allows to  measure 
  33.   how much it is growing.  In practice the obstetrician refers his (her) patient 
  34.   to  another physician that knows how to perform the  examination.  This  later 
  35.   physician then sends a report to the obstetrician.  This report should contain 
  36.   the name of the patient, the name of the referring physician, the measurements 
  37.   that were obtained, and the conclusions based on the findings.
  38.  
  39.        Although in real life,  many more information are obtained, these will be 
  40.   sufficient to demonstrate the function that we want to learn.
  41.  
  42.  
  43.  
  44.        Let  us  start with a clean worksheet.  If you are currently  in  another 
  45.   worksheet, save it with:
  46.  
  47.   /File Save (followed eventually by Replace) 
  48.   
  49.        then type 
  50.  
  51.   /Worksheet Erase
  52.   
  53.        If you start afresh, you will be in front of a clean worksheet.
  54.  
  55.        To start by an easy task, lets format the columns. The command to use is:
  56.  
  57.   /Worksheet Column Set 
  58.   
  59.  
  60.  
  61.                                         1
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.        and you then answer to the prompt,  by replacing the suggested value (9), 
  71.   by the values indicated below for each column:
  72.  
  73.   A = 1, B = 22, C = 4, D = 4, E = 6, F = 1, G = 5, H = 5, I = 5, J = 1, 
  74.   K = 5, L = 5, M = 5, N = 1, O = 2
  75.  
  76.        You need to move to each column before setting its width.
  77.  
  78.        Now let us go in column B, row 1, and introduce the label:
  79.  
  80.   D A T A   I N P U T   A R E A
  81.  
  82.        which will define the data input area.  To make it more fancy,  we can go 
  83.   in  column B row 2 (from now on I will refer to the cell address by its  Lotus 
  84.   name: B2), and introduce the label:
  85.  
  86.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       
  87.        which makes a neat underline.  You might have wanted to use \~ instead in 
  88.   B2. You would then have:
  89.  
  90.   /Copy from B2 to B2..D2
  91.        
  92.        Then introduce the following label in the different cells:
  93.  
  94.   C3: ' Data                        
  95.   C4: '# 1                          
  96.   D4: '# 2                          
  97.   E3: ^Mean                         
  98.   G2: 'Predicted age                
  99.   G3: '   in week                   
  100.   G4: '5th                          
  101.   H4: '50th                         
  102.   I4: '95th                         
  103.   K2: 'Predicted size               
  104.   K3: '     in mm                   
  105.   K4: '5th                          
  106.   L4: '50th                         
  107.   M4: '95th                         
  108.   O5: '?                            
  109.   
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.                                         2
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.        Your worksheet should look like this now:
  137.  
  138.   A           B            C   D    E   F  G    H    I  J  K    L    M  NO  
  139.   1  D A T A   I N P U T   A R E A                                           
  140.   2  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       Predicted age   Predicted size     
  141.   3                         Data    Mean     in week           in mm         
  142.   4                        # 1 # 2        5th  50th 95th  5th  50th 95th     
  143.   5                                                                       ?  
  144.  
  145.        Let us now go in F6 and introduce a vertical bar:
  146.   |
  147.   
  148.        and then
  149.  
  150.   /Copy from F6 to F6..F10
  151.   
  152.        next we will do almost the same:
  153.  
  154.   /Copy from F6 to J6..J10
  155.   
  156.        Note  that in some cases it may indeed be easier to type  cell  addresses 
  157.   than to point. Pointing would have implied here that we would have to deanchor 
  158.   the range by pressing BackSpace,  moved to the correct location (J6), reanchor 
  159.   the pointer,  by pressing . and finally extend the range. Note that you do not 
  160.   need to press . twice when defining a range. Once is sufficient, but I find it 
  161.   disturbing to introduce one . and see two appear.
  162.  
  163.        Up to now we have only introduced kid'stuff.  Be patient. We still have a 
  164.   few label to introduce so lets do that now:
  165.  
  166.   B6: "  Biparietal Diameter (mm)
  167.   B7: "Abdominal Diam #1
  168.   B8: "Abdominal Diam #2
  169.   B9: 'Abdominal Perimeter:
  170.   B10: "Estimated Fetal Weight (g) -->
  171.   B11: 'EFW (pounds + ounces)
  172.   D11: 'lbs.
  173.   F11: 'ounces
  174.   
  175.        A word of explanation about these labels. The "Biparietal Diameter" (BPD) 
  176.   is  more or less the distance between the two ears of the baby.  It is a  well 
  177.   established  measurement that is used among other thing to find the age of the 
  178.   baby, and it is used in the formula to derive the baby's weight. The abdominal 
  179.   diameters are two diameters measured at the level of the baby's  liver,  which 
  180.   are  obtained (usually) perpendicular to each other.  The abdominal  diameters 
  181.   are  mainly  used  in  the estimation of  the  baby's  weight.  The  abdominal 
  182.   perimeter  (AP),  as  indicated by its name,  is the perimeter of  the  baby's 
  183.   abdomen,  and is obtained from the two abdominal diameters by a simple formula 
  184.   that  we  will  see  in  a second.  The estimated fetal  weight  (EFW)  is  an 
  185.   approximation  of the weight of the baby.  It is derived from the BPD and  the 
  186.   AP,  through a very complicated formula that we will see in a moment. Finally, 
  187.   since most american patients are not too familiar with the metric system,  the 
  188.   gram  in  which  the EFW is expressed are converted  into  pounds  and  ounces 
  189.   (rounded to the nearest ounce).
  190.  
  191.  
  192.  
  193.                                         3
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.        Your worksheet should look like this now:
  203.  
  204.    A           B            C   D    E   F  G    H    I  J  K    L    M  NO  
  205.   1  D A T A   I N P U T   A R E A                                           
  206.   2  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       Predicted age   Predicted size     
  207.   3                         Data    Mean     in week           in mm         
  208.   4                        # 1 # 2        5th  50th 95th  5th  50th 95th     
  209.   5                                                                       ?  
  210.   6    Biparietal Diameter (mm)          |               |               |   
  211.   7      Abdominal Diam #1               |               |               |   
  212.   8      Abdominal Diam #2               |               |               |   
  213.   9  Abdominal Perimeter:                |               |               |   
  214.   10 Estimated Fetal Weight (g) -->      |               |               |   
  215.   11 EFW (pounds + ounces)     lbs.      ounces                              
  216.   12                                                                         
  217.  
  218.        Please  note  that  we have prepared to take two  measurements  for  each 
  219.   parameter:  Data 1 and 2. All calculation will in fact be based on the mean of 
  220.   these  to  measurements as referred to in column E.  1-2-3 provides  a  "mean" 
  221.   function, which is @AVG(range). We could enter:
  222.  
  223.   E6: @AVG(C6..D6)         
  224.   
  225.        Note that 1-2-3 is smart enough not to average data with empty cells.  If 
  226.   our  user  only introduce one of the two data,  the mean will still  come  out 
  227.   correct.
  228.  
  229.        We   can   refine  this  formula  by  rejecting  values  that   are   not 
  230.   physiologically  possible,  because  they are too big for  instance.  The  BPD 
  231.   should  not  be larger than 105 mm.  To introduce this lets place a  condition 
  232.   that the cell only displays the value if it below a certain limit. To do that, 
  233.   press EDIT (F2), then HOME, and introduce the appropriate changes as described 
  234.   below. When done press return.
  235.  
  236.   E6: @IF(@AVG(C6..D6)<105,@AVG(C6..D6),@ERR)
  237.   
  238.        which means:  If the mean is below the maximum that we have set  up,  let 
  239.   the  cell represent the mean (the second term in the formula),  otherwise (the 
  240.   last  term in the formula) let us display an error.  This would do  the  trick 
  241.   nicely.  It  would  be  nice  that the cells display  something  like  "Please 
  242.   remeasure"  but @if function in 1-2-3 can only deal  with  numbers,  @NA,  and 
  243.   @ERR.  In certain conditions we would like,  however, to avoid this unesthetic 
  244.   ERR  message.  We  could  trap it,  and replace it by a nicer 0.  There  is  a 
  245.   function  called @ISERR that test if the cell contains an error  or  not.  Its 
  246.   general formula is 
  247.  
  248.   @ISERR(condition, response if condition true, response if condition is false)
  249.  
  250.        We can therefore modify our formula to read:
  251.  
  252.   E6: @IF(@ISERR(@IF(@AVG(C6..D6) <105,@AVG(C6..D6),@ERR)),0,@AVG(C6..D6))
  253.   
  254.        Now you may want to play with the worksheet. First save it under the name 
  255.   BABY by typing:
  256.  
  257.  
  258.  
  259.                                         4
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.   /File Save BABY ~
  269.   
  270.        The ~ sign refers to the <Return> key. You can now enter values in C6 and 
  271.   D6,  and  observe the reaction of the worksheet.  When ready for more,  let us 
  272.   save a lot of efforts, and do:
  273.  
  274.   /Copy from E6 to E7
  275.   
  276.        Which  introduces  the same formula for the next line.  We have  a  small 
  277.   modification to do:  the upper limit for normal here in 120 mm and not 105. So 
  278.   press Edit (F2), then Home, then a couple of TAB and introduce the change. Now 
  279.   you can copy the correct formula into the next line:
  280.  
  281.   /Copy from E7 to E8
  282.   
  283.        You should have:
  284.  
  285.   E6: @IF(@ISERR(@IF(@AVG(C6..D6) <105,@AVG(C6..D6),@ERR)),0,@AVG(C6..D6))
  286.   E7: @IF(@ISERR(@IF(@AVG(C7..D7) <120,@AVG(D7..C7),@ERR)),0,@AVG(C7..D7))
  287.   E8: @IF(@ISERR(@IF(@AVG(C8..D8) <120,@AVG(D8..C8),@ERR)),0,@AVG(C8..D8))
  288.   
  289.        To  be  sure that the data are displayed with only one  digit  after  the 
  290.   period, go to C6 and type
  291.  
  292.   /Range Format Fixed           and enter 1 to replace the suggested 2
  293.   
  294.        The cells E6 to E8 should now read:
  295.  
  296.   E6: (F1) @IF(@ISERR(@IF(@AVG(C6..D6) <105,@AVG(C6..D6),@ERR)),0,@AVG(C6..D6))
  297.   E7: (F1) @IF(@ISERR(@IF(@AVG(C7..D7) <120,@AVG(D7..C7),@ERR)),0,@AVG(C7..D7))
  298.   E8: (F1) @IF(@ISERR(@IF(@AVG(C8..D8) <120,@AVG(D8..C8),@ERR)),0,@AVG(C8..D8))
  299.   
  300.        If you want to get rid of the values that you have introduced in the data 
  301.   area C6..D8, just type
  302.  
  303.   /Range Erase C6..D8
  304.   
  305.        We  can now introduce a simple formula.  The formula for a  circumference 
  306.   (C)  is:  C  = Pi*D where Pi is the greek letter,  and D the diameter  of  the 
  307.   circle. Let us assume that similarly, the abdominal perimeter (AP) is equal to 
  308.   the  mean of the two abdominal diameters multiplied by PI (the greek  letter). 
  309.   We thus would have:
  310.  
  311.   C9: (E7+E8)*@PI/2
  312.   
  313.        This  is fine,  except that we could improve it slightly by using a value 
  314.   for @PI/2 since this is a constant that will never change. To do that, lets go 
  315.   into C9, and correct the formula to:
  316.  
  317.   C9: @PI/2
  318.   
  319.        and then while still in C9,  press <EDIT> then <CALC>.  This will convert 
  320.   the formula into its value.  This will save 1-2-3 one computation,  each  time 
  321.   the worksheet is recalculated. The value should appear as:
  322.  
  323.  
  324.  
  325.                                         5
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.   C9: 1.5707963268
  335.   
  336.        We  can now complete the formula by pressing <EDIT> again and  completing 
  337.   the formula to read:
  338.  
  339.   C9: 1.5707963268*(E7+E8)
  340.   
  341.        We can now introduce the formula for the estimated fetal weight.  This is 
  342.   unfortunately  a long and complicated formula.  This formula was developed  by 
  343.   Sheppard et al. from Yale University.
  344.  
  345.   E10:
  346.   10^(-1.7492+0.166*(E6/10)+0.046*(C9/10)-2.646*((C9/10)*(E6/10))/1000))*1000
  347.   
  348.        I know it looks terrible,  but that's why having a computer is great: you 
  349.   introduce  it  once and you can use it forever !  Another thing is  definitely 
  350.   puzzling.  How come that the cell E10 displays the value:  17.81 when we  have 
  351.   not  introduced any value ?  This is due to the fact that the equation  starts 
  352.   with  an  independent term 1.7492,  and that when everything else is equal  to 
  353.   zero, the cell provide the value of: (10^(-1.7492))*1000.
  354.  
  355.        The  formula as it is now is (almost) correct.  We will see in a  moment, 
  356.   that it still contains a small bug.  It is however barely readable. These cell 
  357.   addresses  are difficult to read.  To change that,  let us go in cell  E6  and 
  358.   type:
  359.  
  360.   /Range Name Create 
  361.   
  362.        and give the name
  363.  
  364.   BPD<Return><Return>
  365.   
  366.        The  second  <Return>  serve to define that only cell E6  in  the  range. 
  367.   Similarly lets go in cell C9 and type:
  368.  
  369.   /Range Name Create 
  370.   
  371.        and give the name
  372.  
  373.   ABD_PER<Return><Return>
  374.   
  375.        You  might be tempted to have given a name such as AP.  Try to avoid this 
  376.   practice. First it may be too short to be meaningful, and second, you might by 
  377.   error give it a number such as AP1, AP2... if you have many range referring to 
  378.   similar information. You would then be in deep trouble. Those name are in fact 
  379.   cell addresses, and 1-2-3 will use the value in the cell AP1, not in the range 
  380.   that you meant to give this name ! This is an important pitfall and be careful 
  381.   to remember it: it might otherwise be quite difficult to debug your formulas ! 
  382.   Now  go  in cell E10,  and surprise the formula is now a lot  more  clear.  It 
  383.   reads:
  384.  
  385.   E10:10^(-1.7492+0.166*(BPD/10)+0.046*(ABD_PER/10)-2.646 *
  386.   ((ABD_PER/10)*(BPD/10))/1000))*1000
  387.   
  388.        What about this pitfall that I mentioned earlier ?  Go into cell C6,  and 
  389.  
  390.  
  391.                                         6
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.   introduce  a value.  Immediately 1-2-3 answers by giving you a value  for  the 
  401.   EFW.  This is incorrect,  since the formula requires that you also provide the 
  402.   value  for the abdominal diameters.  You therefore have a wrong answer in your 
  403.   EFW,  although  nothing tells you about it in the worksheet.  This is  a  very 
  404.   important point.  The worksheet is totally stupid.  It calculates whatever you 
  405.   want, but it is your responsibility to be sure that the calculations are based 
  406.   on  the  correct values,  and that all values needed for the calculations  are 
  407.   present.  The solution is however quite simple. We have to introduce a formula 
  408.   that says, if any of the data is absent, do not calculate, and display 0. This 
  409.   is the formula:
  410.  
  411.    @IF(BPD=0#OR#E7=0#OR#E8=0,@FALSE,otherwise give the result of the formula)
  412.  
  413.        The formula would then become:
  414.  
  415.   E10:@IF(BPD=0#OR#E7=0#OR#E8=0,@FALSE,
  416.   @ROUND((10^(-1.7492+0.166*(BPD/10) + 
  417.   0.046*(ABD_PER/10)-2.646*((ABD_PER/10)*(BPD/10))/1000))*1000,0))
  418.   
  419.        The @ROUND function is introduce to avoid value smaller than a gram:  the 
  420.   formula  is not that accurate,  and it would give a false sense of  precision. 
  421.   Let us give it a name by typing:
  422.  
  423.   /Range Name Create 
  424.   
  425.        and give the name
  426.  
  427.   EFW<Return><Return>
  428.   
  429.        Our formula is now complete, and you can enjoy it by entering a few value 
  430.   in C6..D8. It is also a good time to save your worksheet if you have not taken 
  431.   the  habit to do that frequently.  By the way,  when you work on  a  difficult 
  432.   worksheet,  it  will  not be impossible that a worksheet that  was  originally 
  433.   correct,  become all messed up at some point. If you only save it, and replace 
  434.   the  old  worksheet,  chances  are  that soon or later you will  have  lost  a 
  435.   previously correct formula.  So it is a good habit to save successive version, 
  436.   such as Stage1, Stage2, Stage3 etc ...
  437.  
  438.        Another  pearl:  Suppose  that  you  would  like to  have  a  copy  of  a 
  439.   complicated formula such as the one in E10,  somewhere else in the  worksheet. 
  440.   What would you do:  /Copy it ?  Well yes and no. If you /Copy it, and have not 
  441.   be  careful to use absolute addresses (the $ sign in front of both the  letter 
  442.   and the number portion of the cell address) you will end up will a complicated 
  443.   formula,  that  is  totally  garbelled  up.  If it is far  from  its  original 
  444.   location,  it might be a real pain to fix it.  A much simpler solution is  the 
  445.   following.  Go into the cell that you want to copy.  Press EDIT,  than HOME, ' 
  446.   and then RETURN.  What you have done it transform the formula into a very long 
  447.   label.  You  can now /Copy this label where ever you want.  To make use of it, 
  448.   just do the reverse maneuver:  press EDIT, HOME, then DEL, and then RETURN. Of 
  449.   course you have to do that in the original cell too.
  450.  
  451.        We  have  two small formula to include now.  They will  convert  the  EFW 
  452.   expressed in grams into its value in pounds and ounces:
  453.  
  454.   C11: @INT(EFW/453)
  455.  
  456.  
  457.                                         7
  458.  
  459.  
  460.  
  461.  
  462.  
  463.   
  464.  
  465.  
  466.   
  467.        This find the largest integer of the EFW divided by the conversion factor 
  468.   between pounds and gram which is 453. Let us give C11 a name by typing:
  469.  
  470.   /Range Name Create 
  471.   
  472.        and give the name
  473.  
  474.   LBWGT<Return><Return>
  475.   
  476.        We  now have to calculate how many ounces there are.  To do this we  will 
  477.   take  the difference between the EFW,  and its larger integer in  pounds.  The 
  478.   rest  is what should be converted in ounces.  The number of ounces will be the 
  479.   differences  divided by the conversion factor from grams to ounces,  which  is 
  480.   28.  And we also would like to round the value,  to avoid false precision. The 
  481.   formula will then be:
  482.  
  483.   E11: @ROUND((EFW-LBWGT*453)/28,0)
  484.   
  485.  
  486.        You  have noticed that we haven't filled the formula for the  columns  on 
  487.   the right of F. This will come later: we first need some other parameters.
  488.  
  489.        Before saving the worksheet again, lets introduce two last labels:
  490.  
  491.   B13: 'C O M M E N T S:
  492.   B14: '~~~~~~~~~~~~~~~~
  493.   
  494.   Your worksheet should look like this now:
  495.  
  496.  
  497.    A           B            C   D    E   F  G    H    I  J  K    L    M  NO  
  498.   1  D A T A   I N P U T   A R E A                                           
  499.   2  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       Predicted age   Predicted size     
  500.   3                         Data    Mean     in week           in mm         
  501.   4                        # 1 # 2        5th  50th 95th  5th  50th 95th     
  502.   5                                                                       ?  
  503.   6    Biparietal Diameter (mm)      0.0 |               |               |   
  504.   7      Abdominal Diam #1           0.0 |               |               |   
  505.   8      Abdominal Diam #2           0.0 |               |               |   
  506.   9  Abdominal Perimeter:    0                                               
  507.   10 Estimated Fetal Weight (g) -->    0 |               |               |   
  508.   11 EFW (pounds + ounces)   0 lbs.    0 ounces                              
  509.   12                                                                         
  510.   13 C O M M E N T S:                                                        
  511.   14 ~~~~~~~~~~~~~~~~                                                        
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.                                         8
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.   2) Part II
  533.  
  534.        In the previous part,  we have dealt exclusively with the introduction of 
  535.   numbers.  We now have to introduce the "administrative data", such as the name 
  536.   of the patient,  physician,  etc... The first part will be exceedingly simple: 
  537.   we  will set the column width.  See the first part if you are not too sure how 
  538.   to do it. Let us set the column width to:
  539.  
  540.   P = 25, Q = 3, R = 1, S = 3, T = 1, U = 4, V = 10, W = 10, X = 9
  541.  
  542.        Then, just introduce the following series of labels:
  543.  
  544.   P1: "Patient's information:
  545.   P2: "Last Name :
  546.   P3: "First Name :
  547.   P4: "Birthday (MM/DD/YY) :
  548.   P6: "Referring physician:
  549.   P9: "Operator:
  550.   P12: "LMP (MM-DD-YY):
  551.   P13: "Nbr of days elapsed:
  552.   P14: "Nbr of weeks elapsed:
  553.   P15: "Due Date (from LMP) :
  554.   P17: 'Please move the cursor with the <-- and --> arrow
  555.   P18: 'When you have seen the age, type an extra <RETURN>
  556.   
  557.        To make it more fancy go in P1 and type:
  558.  
  559.   /Range Unprotect <Return><Return>
  560.   
  561.        which will display the label in high intensity.  Then do the same in  P6, 
  562.   and P9. Then introduce a 
  563.  
  564.   '/ 
  565.   
  566.        in R4, T4, R12, T12. Do not forget the apostrophe, or else you initiate a 
  567.   command. Finally introduce the following labels:
  568.  
  569.   W1: '<-- Today's Date
  570.   W4: '<-- Patient's age
  571.   W13: 'days
  572.   W14: 'weeks
  573.    
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.                                         9
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.        Your worksheet should now look like this:
  599.  
  600.  
  601.                   P             Q R S T U      V         W         X
  602.   1     Patient's information:                       <-- Today's Date
  603.   2                Last Name :   
  604.   3               First Name :
  605.   4      Birthday (MM/DD/YY) :    /   /              <-- Patient's age
  606.   5
  607.   6       Referring physician:
  608.   7
  609.   8
  610.   9                  Operator:
  611.   10
  612.   11
  613.   12           LMP (MM-DD-YY):    /   /             
  614.   13      Nbr of days elapsed:                       days
  615.   14     Nbr of weeks elapsed:                       weeks
  616.   15     Due Date (from LMP) :                   
  617.   16
  618.   17  Please move the cursor with the <-- and --> arrow
  619.   18  When you have seen the age, type an extra <RETURN>
  620.  
  621.  
  622.        This  is  fairly self explanatory,  except maybe for the LMP.  LMP  is  a 
  623.   common  abbreviation  that  refers to the Last Menstrual Period.  This  is  an 
  624.   important date since this is how the length of the gestation is counted. It is 
  625.   true that the baby is only conceived around 15 days after the first day of the 
  626.   LMP, but it is easier to count the gestation from the LMP, since most pregnant 
  627.   patients know the date of the LMP,  and few the date of the conception. As you 
  628.   suspect,  we will introduce a few formula in here too.  You might expect  that 
  629.   the first would be something like @TODAY in V1.  Well not quite. If we were to 
  630.   do that, we would always have the current day in the worksheet, and if we were 
  631.   to reload in memory a worksheet save a few days or weeks earlier, the new date 
  632.   would  erase the old date,  and mess up all the calculations saved in the  old 
  633.   worksheet.  What we need,  is more like a "stamping" of the date.  We will see 
  634.   the  trick used for that later.  For now lets give the name DATE to the  range 
  635.   V1.  See  in the earlier portion of this article if you are not too  confident 
  636.   about how to do this.
  637.  
  638.        The  next  obvious  formula that you want to introduce is  the  one  that 
  639.   calculates the patient's age. But before doing that lets name the 3 ranges Q4, 
  640.   S4, U4, with the following names: 
  641.  
  642.   Q4: MBIRTH
  643.   S4: DBIRTH
  644.   U4: YBIRTH
  645.   
  646.        The  formula for the age of the patient is today's date - the birthday of 
  647.   the patient,  divided by 365. Since the age on someone is usually expressed in 
  648.   years  (for  instance 34),  without the decimal portion of the  year  (not  as 
  649.   34.68), we have to trim this with the @INT function. The formula then becomes:
  650.  
  651.   V4: @INT((@TODAY-@DATE(YBIRTH,MBIRTH,DBIRTH))/365)
  652.   
  653.  
  654.  
  655.                                        10
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.        In fact it would be more correct to use 365.25,  instead of 365,  to take 
  665.   into account the 29th of February that occurs every 4 years.  But, again, this 
  666.   is irrelevant precision. As for the formula to obtain the EFW earlier, we have 
  667.   to  make sure that all portion of the birthday are filled.  If one was missing 
  668.   the  calculation would be meaningless,  and we would like the cell to  display 
  669.   that the value is not available (@NA). We can therefore correct the formula to 
  670.   become:
  671.  
  672.   V4: @IF(YBIRTH=0#OR#MBIRTH=0#OR#DBIRTH=0,@NA,
  673.   @INT((@TODAY-@DATE(YBIRTH,MBIRTH,DBIRTH))/365))
  674.   
  675.        It  will  probably strike some of you that this formula  still  allows  a 
  676.   potential pitfall.  Think about it. What if you introduced as the year portion 
  677.   of  the birthday as being 23 (short for 1923).  What would happen ?  Nothing ? 
  678.   Well that is the problem. The medical literature as never recorded a pregnancy 
  679.   in a 62 years old woman. So this formula does not account for this problem. Of 
  680.   course  we could include a statement such as @IF age > than 45  years  display 
  681.   ERR.  That is to crude for our great program, and we will see how we can solve 
  682.   this later.  Make a note (in your SideKick, or whatever else to check for this 
  683.   later.
  684.  
  685.        The next formula that we can introduce is the one in V12,  that will find 
  686.   the  Lotus 1-2-3 serial number of the days of the LMP.  This one is a  formula 
  687.   straight out of the box: 
  688.  
  689.   V12: @DATE(U12,Q12,S12)
  690.   
  691.        Since the serial number type of display,  is difficult to read,  for most 
  692.   of  us,  lets  transform it into something more understandable,  by using  the 
  693.   following command:
  694.  
  695.   /Range Format Date 1 <Return>
  696.   
  697.        And lets give it the name LMPDATE.  By now you should be expert at giving 
  698.   names.
  699.  
  700.        From the value obtained in V12, we can compute how many days have elapsed 
  701.   since  the  beginning of the gestation.  The formula is  very  simple,  it  is 
  702.   today's date - the date of the LMP.  This is really of example where the Lotus 
  703.   date arithmetic is tremendous. The formula is:
  704.  
  705.   V13: +DATE-V12
  706.   
  707.        However  such  a  simple  formula  does not  account  for  error  in  the 
  708.   introduction of the values.  We can trap them in a simple way by checking that 
  709.   the number of days that have elapsed,  is less than the maximal number of days 
  710.   of  a  normal gestation.  Since a normal gestation is 40 weeks (280 days)  and 
  711.   that the baby may be as much as 14 days late,  if we assume 320 days we should 
  712.   be able to cover even the most rare case, and the patients whose ovulation are 
  713.   delayed.  The number of days that have elapsed,  should also be more than 0 of 
  714.   course. Thus the enhanced formula:
  715.  
  716.   V13: @IF((DATE-V12)>0#AND#(DATE-V12)<320,DATE-V12,@ERR)
  717.   
  718.        Another  relation  which  is  easy  to  obtain,   and  is  used  in  many 
  719.  
  720.  
  721.                                        11
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.   calculations in the number of weeks that have elapsed,  in other word, the age 
  731.   of the baby. This formula is straight forward:
  732.  
  733.   V14: +($V$13/7)
  734.   
  735.        Since we do not want all the number behind the period, we will get rid of 
  736.   them.  The  way  we have gotten rid of unnecessary numbers previously  was  by 
  737.   taking the @INTeger of the number.  We cannot do this here, since as mentioned 
  738.   earlier,  this value is going to be used in some following calculations.  What 
  739.   we  in fact want is to keep the value as it is,  but only show the integer  of 
  740.   the number of weeks. This is done by formatting the cell
  741.  
  742.   /Range Format Fixed 0
  743.   
  744.        Since this is the age of the baby,  why not call this cell AGE, this will 
  745.   make further calculations a lot easier.
  746.  
  747.   /Range Name Create AGE~
  748.   
  749.        We can also calculate when the baby should be expected.  This is commonly 
  750.   called the Due Date.
  751.  
  752.   V15: (D1) @IF(@ISERR(LMPDATE),@ERR,@IF(@ISERR(V13),@ERR,LMPDATE+280))
  753.   
  754.        You will have noticed that the cell will only display a result,  when two 
  755.   conditions are filled:  the LMPDATE is available,  and is valid, as checked by 
  756.   the number of days elapsed (V13).  Again you should fixe the cell attribute to 
  757.   display the date format #1, as you previously did in V12.
  758.  
  759.        Your screen should look like this now:
  760.  
  761.  
  762.  
  763.                   P             Q R S T U      V         W         X
  764.   1     Patient's information:             01-Mar-85 <-- Today's Date
  765.   2                Last Name :  1
  766.   3               First Name :
  767.   4      Birthday (MM/DD/YY) :    /   /           NA <-- Patient's age
  768.   5
  769.   6       Referring physician:
  770.   7
  771.   8
  772.   9                  Operator:
  773.   10
  774.   11
  775.   12           LMP (MM-DD-YY):    /   /          ERR
  776.   13      Nbr of days elapsed:                   ERR days
  777.   14     Nbr of weeks elapsed:                   ERR weeks
  778.   15     Due Date (from LMP) :                   ERR
  779.   16
  780.   17  Please move the cursor with the <-- and --> arrow
  781.   18  When you have seen the age, type and extra <RETURN>
  782.  
  783.  
  784.  
  785.  
  786.  
  787.                                        12
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.        This  screen is now finished.  It contains important information that  we 
  797.   can  now use to complete the right portion of the screen that we developed  in 
  798.   the  last session.  As you remembered,  we left the first screen to look  like 
  799.   this:
  800.  
  801.  
  802.    A           B            C   D    E   F  G    H    I  J  K    L    M  NO  
  803.   1  D A T A   I N P U T   A R E A                                           
  804.   2  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       Predicted age   Predicted size     
  805.   3                         Data    Mean     in week           in mm         
  806.   4                        # 1 # 2        5th  50th 95th  5th  50th 95th     
  807.   5                                                                       ?  
  808.   6    Biparietal Diameter (mm)      0.0 |               |               |   
  809.   7      Abdominal Diam #1           0.0 |               |               |   
  810.   8      Abdominal Diam #2           0.0 |               |               |   
  811.   9  Abdominal Perimeter:    0                                               
  812.   10 Estimated Fetal Weight (g) -->    0 |               |               |   
  813.   11 EFW (pounds + ounces)   0 lbs.    0 ounces                              
  814.   12                                                                         
  815.   13 C O M M E N T S:                                                        
  816.   14 ~~~~~~~~~~~~~~~~                                                        
  817.  
  818.  
  819.        As  we mentioned earlier,  the BPD can be used to predict the age of  the 
  820.   baby,  and we should now be able to complete this.  Besides, since we now know 
  821.   what is the age of the baby (from the LMP),  we can predict what should be the 
  822.   size of the BPD,  and what should be its weight. This is important, since when 
  823.   the user of our worksheet will introduce his numbers, it would be nice to tell 
  824.   him what size to expect,  so that a grossly abnormal value can be  remeasured, 
  825.   or verified.  The predictions,  however,  are never absolute. There are always 
  826.   baby that are destined to be bigger or heavier than other. Therefore we should 
  827.   take that into account. You suspected that by the fact that we have introduced 
  828.   label  for the 5th,  50th (mean) and 95th percentile confidence  limits.  What 
  829.   this means, is that there is 90% chances that the measurements obtained on the 
  830.   baby  that  is investigated will fall between the lower and higher  confidence 
  831.   limits.  Should  it be falling outside,  one might suspect that  something  is 
  832.   abnormal with the baby.
  833.  
  834.        The equation to predict the normal size of the BPD is:
  835.  
  836.   L6: -19.634+3.0209*AGE+0.042134*AGE^2-0.0011756*AGE^3
  837.   
  838.        Here  we  can see the advantage of the use of name  ranges.  The  formula 
  839.   appears a lot clearer, than if cell addresses had been used. If when you press 
  840.   return,  1-2-3  beeps at you,  and you have checked that the formula is indeed 
  841.   correct,  the  problem  is  that you have forgotten  to  name  the  range,  as 
  842.   suggested  previously.  It would be a pity to have to press ESC to go name the 
  843.   range:  this  would  erase all the equation that you have  entered,  a  pretty 
  844.   tedious  job.  If  you  know the cell address you could edit  the  formula  by 
  845.   replacing AGE by the cell address.  To show you another technique,  O will not 
  846.   remind you of what the cell address was.  The trick previously used to copy  a 
  847.   formula at long distance without having to change all the cell addresses,  can 
  848.   be used here again.  While in the EDIT mode, press HOME, and add an apostrophe 
  849.   at  the  very beginning of the formula.  As the upper right indicator on  your 
  850.   screen  mentions,  by  doing that you have transformed a formula into  a  long 
  851.  
  852.  
  853.                                        13
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.   label,  that 1-2-3 can now accept.  Now that you have saved your work,  go and 
  863.   /Range Name the cell V14 and call it AGE.  When you return to L6,  press  EDIT 
  864.   again,  HOME,  and delete the '.  Now 1-2-3 will accept the formula.  Remember 
  865.   this  trick.  It is very useful when you introduce long formula.  Some formula 
  866.   can  reach  240 characters.  You won't be able to see them  entirely  in  your 
  867.   screen:  they will scroll right or left.  Such long formula can be terrible to 
  868.   debug,  and it is not always possible to split them in shorter pieces. In such 
  869.   cases the above trick allows you to get out of it, you can then use the 
  870.   /Print Printer Option Other Cell-Formula Quit Range ~ Go Quit
  871.   to get a printed copy of the formula,  whic is now a label.  Often the problem 
  872.   will  be unbalanced parenthesis,  or incorrect use of the #AND#,  #OR# kind of 
  873.   parameters.
  874.  
  875.        After this slight disgression, let us return to our formula in L6. As you 
  876.   have  noticed,  it  appears  that there is a bug:  although no  age  has  been 
  877.   introduced,  it displays the value -19.634. Again this is the independent term 
  878.   of the polynomial equation.  This demonstrates that polynomial equation should 
  879.   not  be used outside their limit of definition.  To trap this error lets  edit 
  880.   the  formula to make sure that nothing is displayed in the cell if the AGE  is 
  881.   less then 12 weeks:
  882.  
  883.   L6: @IF(AGE<12,0,-19.634+3.0209*AGE+0.042134*AGE^2-0.0011756*AGE^3)
  884.   
  885.        We can now introduce the confidence limits.  These are equal to the  age, 
  886.   less (or plus) 1.66 standard deviations:
  887.  
  888.   K6: @IF(AGE<12,0,L6-(1.66*2.75373))
  889.   M6: @IF(AGE<12,0,L6+(1.66*2.75373))
  890.                                                                              
  891.  
  892.        Following exactly the same principle, we can also introduce the predicted 
  893.   age from the BPD in cell H6,  as well as the confidence limits in cells G6 and 
  894.   I6:
  895.  
  896.   H6: (G) @IF(E6=0,0,2.810638+0.4665383*E6-0.003687003*E6^2+0.0000282043*E6^3)
  897.   G6: (G) @IF(H6=0,0,H6-(1.66*1.08))
  898.   I6: (G) @IF(H6=0,0,H6+(1.66*1.08))
  899.   
  900.        We  can  add  one  more  "bell  and  whistle"  by  having  the  worksheet 
  901.   automatically  flag  for  us if the value of the BPD is within  the  predicted 
  902.   size, or if it outside. The formula is:
  903.  
  904.   O6: @IF(E6=0,0,@IF(E6<K6#OR#E6>M6,1,0))
  905.   
  906.        which would display a "1" if the BPD is outside the confidence limits, or 
  907.   a 0 if it is within.
  908.  
  909.        We  can now introduce the equation to determine the  predicted  estimated 
  910.   fetal weigh. This is a difficult equation, it contain some exponentiation, and 
  911.   is almost a mile long:
  912.  
  913.   L10: 10^(0.5328769+0.1122225*AGE-0.000145731*AGE^2-0.0000202932*AGE^3)
  914.   
  915.        We  have to make sure that the cell will not display wrong information by 
  916.   modifying it to look like:
  917.  
  918.  
  919.                                        14
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.   L10: @IF(AGE<15,0,10^(0.5328769+0.1122225*AGE-0.000145731*AGE^2
  930.   -0.0000202932*AGE^3))
  931.   
  932.        and the standard deviation would be:
  933.  
  934.   K10:@IF(L10=0#OR#AGE<15,0,L10-(10^(-2.72529+0.4042264*AGE-
  935.   0.01048152*AGE^2+0.000098495*AGE^3)))
  936.  
  937.   M10:@IF(L10=0#OR#AGE<15,0,L10+(10^(-2.573974+0.4008528*AGE-
  938.   0.01031992*AGE^2+0.0000961377*AGE^3)))
  939.   
  940.        Wheew, this was the last equation. By now no equations should ever threat 
  941.   you  anymore  !  Lets  call the 5th percentile  (K10)  LOWEFW,  and  the  95th 
  942.   percentile (M10) HIGHEFW,  using the /Range Name Command.  We can now fill the 
  943.   last formula, that will check whether our baby is within or outside the normal 
  944.   weight predictions for its age:
  945.  
  946.   O10: @IF(EFW=0,0,@IF(EFW=0#OR#HIGHEFW=0,0,@IF(EFW<LOWEFW#OR#EFW>HIGHEFW,1,0)))
  947.   
  948.   You now have finished all the input screens, and your first screen should look 
  949.   like:
  950.  
  951.  
  952.    A           B            C   D    E   F  G    H    I  J  K    L    M  NO  
  953.   1  D A T A   I N P U T   A R E A                                           
  954.   2  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       Predicted age   Predicted size     
  955.   3                         Data    Mean     in week           in mm         
  956.   4                        # 1 # 2        5th  50th 95th  5th  50th 95th     
  957.   5                                                                       ?  
  958.   6    Biparietal Diameter (mm)      0.0 |   0    0    0 | ERR  ERR  ERR |0  
  959.   7      Abdominal Diam #1           0.0 |               |               |   
  960.   8      Abdominal Diam #2           0.0 |               |               |   
  961.   9  Abdominal Perimeter:    0                                               
  962.   10 Estimated Fetal Weight (g) -->    0 |               | ERR  ERR  ERR |0
  963.   11 EFW (pounds + ounces)   0 lbs.    0 ounces                              
  964.   12                                                                         
  965.   13 C O M M E N T S:                                                        
  966.   14 ~~~~~~~~~~~~~~~~                                                        
  967.  
  968.        
  969.        Well  done.  But  that is not too terrifically exciting to move all  over 
  970.   these two screens to introduce data. Isn't there any better system ? Of course 
  971.   there  is,  and  this  will be the third part.  Do not  forget  to  save  your 
  972.   worksheet if you have not taken the habit to do it every 5 minutes or so.
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.                                        15
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.   3) Part III: Using Macros
  995.  
  996.        In  the first two installments we have prepared a fairly complicated sets 
  997.   of data entry forms,  in which most of Lotus 1-2-3 formula and error  trapping 
  998.   have been used. To complete this quick teaching of the advanced features of 1-
  999.   2-3,  will  will  now use an extensive series of macro to make the data  entry 
  1000.   easier, and even to use 1-2-3 for word processing !
  1001.  
  1002.        Lets start by retrieving the worksheet.  Press HOME,  you should see  the 
  1003.   data  entry  form  for the measurements.  Press TAB once.  You  now  have  the 
  1004.   patient's  information  entry form.  Pressing TAB again bring you in an  empty 
  1005.   screen.  For a change we will accept the default size of the column. Columns Y 
  1006.   to AF should be visible now. Go in Z1 and type:
  1007.  
  1008.   Z1: 'MACROS
  1009.   
  1010.        Let us go in cell Y4 and enter the label:
  1011.  
  1012.   Y4: '\M       
  1013.   
  1014.        and in 
  1015.  
  1016.   Z4: '{GOTO}message~/XMmenu~
  1017.   
  1018.        What does this last label means ? Well this will be our first macro. Note 
  1019.   that it starts with an apostrophe.  Although it is not always necessary to  do 
  1020.   so,  I  would  strongly  advise you to do so.  A 1-2-3 macro is  a  series  of 
  1021.   instructions  that can be invoqued by pressing a single combination of ALT and 
  1022.   one  letter.   The {GOTO} is the way to place in the macro one of the  special 
  1023.   keys  of  the  IBM PC keyboard.  You simply type its name  between  the  curly 
  1024.   brackets.  Your 1-2-3 manual has the list of all the keys that can be used  in 
  1025.   the macro, and the macro spelling of their name. Here we ask the program to go 
  1026.   to  a place called "message".  This is simply a range that we will define that 
  1027.   will  contain a message.  This is a handy technique.  If you want to tell  the 
  1028.   user of your worksheet long stories about what they should do at what  moment, 
  1029.   you can include a series of message in the worksheet, and send the program the 
  1030.   these  location.  Alternatively,  you can /Range Erase the message range,  and 
  1031.   include  its content within the macro.  The macro will then type it  for  you. 
  1032.   This last technique is slightly slower,  but more flexible.  Please note,  and 
  1033.   this is crucial,  the ~ sign,  just after message. This is the spelling of the 
  1034.   key  RETURN,  in 1-2-3 language.  Since you cannot include a Return within the 
  1035.   macro,  (this would terminate the entry) 1-2-3 has given a simple name to  the 
  1036.   Return key,  which is by far the key that you will need the most.  You have to 
  1037.   include  a ~ every time that you would have pressed returned if you were to do 
  1038.   the  series  of command yourself.  An easy trick is to perform the  series  of 
  1039.   commands  yourself  noting VERY carefully what key  you  press.  Be  extremely 
  1040.   careful about ~ and spacebar.  These are the two major offenders, and 1-2-3 is 
  1041.   absolutely not forgiving. 
  1042.  
  1043.        Alternatively,  if  you are a Prokey User,  you can store the macro in  a 
  1044.   Prokey   key,   exit   from  1-2-3,   write  the  new  Prokey  macro   (prokey 
  1045.   filename.pro/w),  and then import it into your worksheet with the /File Import 
  1046.   Text. You will have to change the key names, delete the <begdef> and <enddef>, 
  1047.   and  the  *.  This  may  look tedious,  but it can save  a  lot  of  time  for 
  1048.   complicated  macro.  As  you can see there is something more in the  label  we 
  1049.  
  1050.  
  1051.                                        16
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.   introduce:  /XMmenu~. This is a special macro instruction that tell 1-2-3 that 
  1061.   a special command (/X) is about to come. The special command in this case is a 
  1062.   Menu  (M)  called menu.  This may appear terribly confusing !  In fact  it  is 
  1063.   fairly  simple.  1-2-3 allows you to make your own menus just like the one you 
  1064.   see when pressing /. And that is what we are about to do. 
  1065.  
  1066.        Another  very important thing to know,  is that a macro is just a  label, 
  1067.   until you give it a name.  This name MUST be \ plus one letter,  and only that 
  1068.   (for one single exception that we will see later).  The letter can be upper or 
  1069.   lower case,  it does not matter. Now it starts to make sense why we introduced 
  1070.   this mysterious \M label in Y4. This is going to be the name of the macro that 
  1071.   we have introduce in Z4. 
  1072.  
  1073.        It is not mandatory to use this convention, but it is quite convenient to 
  1074.   write down the name of the macro in the left adjacent cell.  The cell that  we 
  1075.   will name, however, is the cell that contains the macro. Lets do it:
  1076.  
  1077.   /Range Name Create \M~~
  1078.   
  1079.        There are two ~.  The first terminates the name,  the second, defines the 
  1080.   range.  You  could cover more than one cell with the macro range for the name. 
  1081.   This is,  however,  not recommended.  If you move this range around, the range 
  1082.   might be stretched, and complications are bounded to occur.
  1083.  
  1084.        Now go in Y5 and type:
  1085.  
  1086.   Y5:'Name
  1087.   
  1088.        This  will be the first entry in our future menu.  Since we said  in  the 
  1089.   previous  macro,  that processing of the macro should continue (/X) in a  menu 
  1090.   (M)  called "menu",  it is logic that we now give the name "menu" to cell  Y5. 
  1091.   Again do a 
  1092.  
  1093.   /Range Name Create Menu~~
  1094.   
  1095.        We  mentioned this "message" range,  but we have not defined it  yet.  So 
  1096.   press  GOTO  (F5) and answer P41.  You will arrive to a virgin section of  the 
  1097.   worksheet. Type:
  1098.  
  1099.   /Range Name Create Message~~
  1100.   
  1101.        then go into P42, and type:
  1102.  
  1103.   Please select an option from the above menu.
  1104.   
  1105.        Then press GOTO again,  and answer Y1. If everything went smoothly, press 
  1106.   <ALT  M> and you should see a new menu in place of the familiar Worksheet  ... 
  1107.   menu.  This one just says Name. Although this is great, it is not yet terribly 
  1108.   exciting ! Press CTRL BREAK and GOTO Y1. There move to Z5, and enter:
  1109.  
  1110.   Z5: 'Data
  1111.   AA5: 'Comments
  1112.   AB5: 'Report
  1113.   AC5: 'Prepare
  1114.   AD5: 'Exit
  1115.  
  1116.  
  1117.                                        17
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.   
  1124.  
  1125.  
  1126.   
  1127.        These  will  be the future tasks that we want our worksheet  to  perform. 
  1128.   Since  the  name  are quite descriptive for you,  you may not  want  to  write 
  1129.   anything  else,  but  since we want anyone to be able to  understand  how  our 
  1130.   worksheet works, lets introduce some information:
  1131.  
  1132.   Y6: 'Enter administrative data for the patient
  1133.   Z6: 'Enter measurements
  1134.   AA6: 'Enter your comments and suggestions regarding this examination
  1135.   AB6: 'Print the report
  1136.   AC6:  "Prepare  for a entering a new patient WARNING:  this erase the  current 
  1137.   data
  1138.   AD6: 'Quit the program, and return to LOTUS Access Menu
  1139.   
  1140.        Now press <ALT M> to see our progress.  Isn't that great ?  It looks just 
  1141.   like  the real thing doesn't it ?  This show an important feature of the  menu 
  1142.   creation  in 1-2-3.  You have to give one name per option,  one option in each 
  1143.   adjacent  cell (no more than 8),  the total length of the option of  the  menu 
  1144.   cannot  exceed  64  characters (otherwise it would bump into the  right  upper 
  1145.   corner command indicator),  and there must be a blank cell to the right of the 
  1146.   last  option.  Secondly,  the  second  line  must either  contain  a  word  of 
  1147.   explanation,  or be blank.  Some of you probably had the curiosity to move  in 
  1148.   this menu.  Note that as with the real 1-2-3 menu you can either point to,  or 
  1149.   press  the first letter.  If you want to give the first letter,  no two option 
  1150.   can  start  with  the same letter.  That why this macro  contains  the  option 
  1151.   "Prepare" instead of the more logical "Clear", which would have interfere with 
  1152.   "Comment"  or  "New" that would have interfered with "Name".  If  two  options 
  1153.   start with the same letter, the first will always be selected if you select by 
  1154.   letter.  Pointing  could work however.  You now realize why when you  want  to 
  1155.   /File  Extract,  you have to press /File Xtract,  and not /File Extract, which 
  1156.   would  have  collided with the /File Erase,  also on the same menu.  This  has 
  1157.   probably  erase  more files than any other peculiarity of 1-2-3.  If  you  can 
  1158.   devise  a  way to rename this Xtract command,  call Mitch,  he might  want  to 
  1159.   included it in the next revision of 1-2-3.
  1160.  
  1161.        Those audacious among you that have selected an option in the menu,  will 
  1162.   have been disappointed:  the only thing that happened was that the upper right 
  1163.   status indicator changed from CMDREADY to READY. Not to impressive. By the way 
  1164.   did  you noticed this CMDREADY ?  When you are executing a  1-2-3  macro,  the 
  1165.   letter  CMD  (for command) are placed in front of most of the  usual  commands 
  1166.   (but not WAIT for instance). 
  1167.  
  1168.        Why  did  nothing happened ?  Why didn't we automatically start  entering 
  1169.   data ? Well we didn't told 1-2-3 what to do. This is the third important point 
  1170.   to  know about the menu in macro.  We have seen what the two first  line  must 
  1171.   contain,  now  we have discovered that in order for 1-2-3 to do something,  we 
  1172.   have to store in the next cell in the same column what should be done. This is 
  1173.   very  important.  A  macro,  can  extend other a very long  series  of  cells, 
  1174.   provided that they are contiguous,  and on top of each other.  Execution  will 
  1175.   stop as soon as 1-2-3 arrives at a blank cell. That makes sense in fact ! Also 
  1176.   note that although we only named one cell (Y5) with the name, all cells to the 
  1177.   right  (only in cases of menu),  and all cells below those are included in the 
  1178.   same menu.
  1179.  
  1180.        Enough theory. Lets introduce those famous instructions that we want 1-2-
  1181.  
  1182.  
  1183.                                        18
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.   3 to do for us.  And lets start by the entering the patient's name and related 
  1193.   information.
  1194.  
  1195.   Y7: '{GOTO}p1~/XIpatname<>1~/XG\M~
  1196.   
  1197.        This tells 1-2-3 to go to cell P1, and to execute a special macro command 
  1198.   (/X) which is "Ipatname<>1~/XG\M~". I stands for If, and "patname' is a range. 
  1199.   A  command  language without IF is not a command language.  The  way  the  /XI 
  1200.   command works is the following.  If the condition that is tested (in this case 
  1201.   if "patname" is different from (<>) 1) is true, than proceed and execute  what 
  1202.   is on the same line (/XG\M~),  otherwise,  drop to the next line,  and execute 
  1203.   the commands on the next line. The /XG\M~ is a macro command (/X) that says to 
  1204.   Go  (G) to another cell,  or range,  or macro (\M) and execute what is inside. 
  1205.   Note that you should not forget the ~ !!! Very important ! 
  1206.  
  1207.        Now  that we know what this is all about,  what does it mean  ?  When  we 
  1208.   introduce the name of the patient, we do not want that by pressing Name (which 
  1209.   will  be the first choice of our menu) by error,  to have to reenter the  name 
  1210.   again.  So we need to see if the patient's name as already been entered. If it 
  1211.   has,  than we just return to the menu,  no harm done.  If it has not,  than we 
  1212.   should enter it. We would therefore like to be able to test if there is a name 
  1213.   in the cell Q1 (go name it "patname", then come back). However, 1-2-3 does not 
  1214.   let us do this. If we ask the value of a label, it will always answer 0, which 
  1215.   is  unfortunately the same answer that we would receive if the cell is  empty. 
  1216.   This  does  not  allows  us to make the test we need.  The  only  solution  is 
  1217.   therefore,  to place a value in the cell ahead of time,  and we choose  1,  in 
  1218.   this case. Then test if the cell has a value different of one. If we introduce 
  1219.   a  label  in  it,  the value 1 will be replaced by 0.  This will allow  us  to 
  1220.   perform  the test,  but I am sure that quite a few of you must think "This  is 
  1221.   totally,  crazy,  it is twice more work !".  Well yes,  and no.  It is  indeed 
  1222.   another  step,  but  you will see later that we can have 1-2-3 do the job  for 
  1223.   you.  That is the second note you should write down for yourself,  and see how 
  1224.   we will solve it later. 
  1225.  
  1226.        Note that by using the {GOTO}p1 instruction, we managed to have the label 
  1227.   stored  in P1 to show in the left upper corner of the screen,  which makes  it 
  1228.   easier for the user to understand what he is doing.
  1229.  
  1230.        Finally,  note  the  convention that upper cases are used to  type  1-2-3 
  1231.   instructions or key names, while lower cases are used to type range name, cell 
  1232.   addresses,  and all the rest. Although this is not mandatory, it will make the 
  1233.   reading  of  your  macro  a  lot  easier.   For  instance  a  macro  such  as: 
  1234.   /PPOOUOCQRPOOR~GQ makes less sense than /PPOOUOCQRpoor~GQ. 
  1235.  
  1236.        Now we can introduce the next commands:
  1237.  
  1238.   Y8: '/XLPatient's LAST NAME:~patname~
  1239.   Y9: '/XLPatient's FIRST NAME:~patfname~
  1240.   
  1241.        They introduce a new type of special macro commands: the /XL. This prompt 
  1242.   the  user  to  input a Label (L),  and it stores it in a  cell  whose  address 
  1243.   follows  the ~.  The prompt can contain some information about what should  be 
  1244.   entered,  in this cases:  Patient's LAST NAME:, and Patient's FIRST NAME:, and 
  1245.   store the information in the cells "patname" and "patfname".  We have  already 
  1246.   named  Q2  as  patname,  go and name Q3 as patfname.  The /XL  command  accept 
  1247.  
  1248.  
  1249.                                        19
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.   anything  including  numbers and blank responses (a simple  return).  This  is 
  1259.   important  to remember.  There is no way to make sure that a user will fill  a 
  1260.   cell that he MUST fill.  The trick described earlier:  preload the cell with a 
  1261.   value,  ask  the  question (/XL),  then test the cell to see if the  value  is 
  1262.   different  from the value that you preloaded,  will not work,  since the  user 
  1263.   could type Return, to the question, therefore erasing the preloaded value, and 
  1264.   fouling  the  test.  This is probably one reason why  innocent  people  bought 
  1265.   Symphony, later to discover that it was so impossible to use !
  1266.  
  1267.        The next command is very similar:
  1268.  
  1269.   Y10: '/XNMONTH of birthday (type 0 if unknown): 
  1270.   ~mbirth~/XImbirth>12~/XGmonthbirth~
  1271.   
  1272.        Since  it  is more than 78 characters it did not fit on a standard  page, 
  1273.   and it was therefore placed on two lines. Here we use the command /XN. This is 
  1274.   the similar command to input a number,  however,  there is a major difference. 
  1275.   The user cannot simply press Return to go to the next question.  He must input 
  1276.   a value.  We therefore need to provide an escape mechanism in case our patient 
  1277.   does  not  want to reveal her age.  Inputing 0 will do.  Since there is  no  0 
  1278.   month,  it should not introduce any confusion in the further  calculation.  If 
  1279.   something  else  than 0 is introduced it will be stored  in  "mbirth".  Again, 
  1280.   please go and name Q4 with this name. 
  1281.  
  1282.        Note  that  this line continues with a IF condition (/XI).  What this  IF 
  1283.   condition does, is check that the value just stored in "mbirth" is larger than 
  1284.   12.  This would refer to an impossible month,  and should be trapped.  If  the 
  1285.   value  is indeed found to be too large,  than processing goes to (/XG) a  cell 
  1286.   called  "monthbirth"  which  as you guessed is Y10.  This allows  to  make  an 
  1287.   infinite loop,  that the user can only escape by given a valid answer,  or a 0 
  1288.   to  indicate that the answer is not available.  Before forgetting  it,  please 
  1289.   name Y10 "monthbirth". 
  1290.  
  1291.        If  the  value  that the user has introduced is  valid,  processing  will 
  1292.   continue at the next line which is:
  1293.  
  1294.   Y11: '/XImbirth=0~/XGphysintro~
  1295.   
  1296.        Again we have an IF condition.  Now we test to see if the value in mbirth 
  1297.   is not 0.  If it is,  than there is no point in asking what is the day or year 
  1298.   or  birth of the patient,  we should continue processing further  down  (/XG), 
  1299.   where  information regarding the referring physician ("physintro") are needed. 
  1300.   As  before  if the tested condition is not true processing drops down  on  the 
  1301.   next line:
  1302.  
  1303.   Y12: '/XNPatient's DAY of BIRTHDAY: 
  1304.   ~dbirth~/XIdbirth>@VLOOKUP(mbirth,mthtable,1)~/XGdaybirth~
  1305.   
  1306.        This  is  basically the same thing,  except that to test if  the  day  is 
  1307.   possible we need a more sophisticated check-up. Indeed the day vary with which 
  1308.   month  is used.  So we should test for the day and the month.  This is  easily 
  1309.   done  using the @VLOOKUP function,  that you may have wonder how in the hell I 
  1310.   would be able to introduce in this tutorial, without referring to some sort of 
  1311.   interest rate kind of table. Well here it is:
  1312.  
  1313.  
  1314.  
  1315.                                        20
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.    Month table: mthtable
  1325.           1       31
  1326.           2       29
  1327.           3       31
  1328.           4       30
  1329.           5       31
  1330.           6       30
  1331.           7       31
  1332.           8       31
  1333.           9       30
  1334.          10       31
  1335.          11       30
  1336.          12       31
  1337.  
  1338.        You should introduce this in 
  1339.  
  1340.   Y19: 'Month table: mthtable
  1341.  
  1342.   Y20: 1              Y26: 7 
  1343.   Z20: 31             Z26: 31
  1344.   Y21: 2              Y27: 8 
  1345.   Z21: 29             Z27: 31
  1346.   Y22: 3              Y28: 9 
  1347.   Z22: 31             Z28: 30
  1348.   Y23: 4              Y29: 10
  1349.   Z23: 30             Z29: 31
  1350.   Y24: 5              Y30: 11
  1351.   Z24: 31             Z30: 30
  1352.   Y25: 6              Y31: 12       
  1353.   Z25: 30             Z31: 31       
  1354.                       
  1355.        The entry in [Y19:  'Month table:  mthtable] is not indispensable, but it 
  1356.   allows you to remember to name of the table (range).  As you know there is  no 
  1357.   direct tricks in 1-2-3 to find the name of a range. When the range covers only 
  1358.   one cell,  than it is easy to /Copy the cell into a neighboring cell.  Then by 
  1359.   going   into  the  neighboring  cell,   the  control  panel  will  tell   you: 
  1360.   +Cell_address,  where  Cell_address will either be letters and number such  as 
  1361.   AE23  for instance,  or it will be the cell name.  This trick does not work if 
  1362.   the  range is more than one cell large,  and the only trick is to  do:  /Range 
  1363.   Name Create, and point to the name that you want to investigate. It is easier, 
  1364.   when  using utility type of range as the one we just create to place its  name 
  1365.   just above. 
  1366.  
  1367.        Now  you should name the whole range Y20..Z31 with the  name  "mthtable". 
  1368.   The formula that we have introduced in Y12 makes more sense now. The
  1369.   [/XIdbirth>@VLOOKUP(mbirth,mthtable,1)~/XGdaybirth~]  means  if  the  date  of 
  1370.   birth  (dbirth) is bigger than the value found by the @VLOOKUP function in the 
  1371.   month table (mthtable) for the month in question (mbirth), in the column which 
  1372.   as an offset of 1,  go to (/XG) daybirth to continue processing. Again, as you 
  1373.   guessed daybirth is Y12, so please go name it accordingly. If the condition is 
  1374.   not filled,  that is if the day is within the correct limits,  than processing 
  1375.   continues on the next line.  Otherwise the user is looped back,  and asked the 
  1376.   same  question again.  We should make the test a little more bullet  proof  by 
  1377.   adding
  1378.  
  1379.  
  1380.  
  1381.                                        21
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.   Y12: '/XNPatient's DAY of BIRTHDAY: 
  1391.   ~dbirth~/XIdbirth<1#AND#dbirth>@VLOOKUP(mbirth,mthtable,1)~/XGdaybirth~
  1392.   
  1393.        which  would trap the malicious user that would try to introduce a day 0, 
  1394.   and fool our worksheet !
  1395.  
  1396.        As you see 1-2-3 is incredibly versatile, and you can test most anything. 
  1397.   Something,  however,  that  you  will not be able to test,  is that  the  user 
  1398.   introduce  a  value such as 23.46 day !  But such a malicious user  should  be 
  1399.   fired anyway !
  1400.  
  1401.        On to the next line.
  1402.  
  1403.   Y13: '/XNPatient's YEAR of BIRTHDAY:
  1404.   ~ybirth~/XI@year(@today)-ybirth>45~/XGyearbirth~
  1405.   
  1406.        You  remember this first note you had to remember about the  patient  age 
  1407.   that  should not be more than 45 years otherwise it would be unlikely that she 
  1408.   gets pregnant ? Well now is the time to attack this problem. What the 
  1409.   [/XI@year(@today)-ybirth>45~/XGyearbirth~] does is test that the year  portion 
  1410.   (@YEAR) of the current date (@TODAY),  minus the year of the patients birthday 
  1411.   (ybirth)  is no greater than 45.  If it is,  than the program will loop  back. 
  1412.   Again please name Y13 with the name "yearbirth".
  1413.  
  1414.        We  now  have to complete a few more entries,  and this should  be  kid's 
  1415.   stuff for you by now !
  1416.  
  1417.   Y14: '{CALC}{GOTO}p6~/XLPhysician's name:~physname~
  1418.   Y15: '{GOTO}p9~/XLOperator:~operator~
  1419.   
  1420.        You are already familiar with the {GOTO} trick. But what about this first 
  1421.   {CALC}  ?  For whatever reason,  when 1-2-3 in processing macro,  it does  not 
  1422.   recalculates  the  worksheet.  Since we would like the age of the  patient  to 
  1423.   appear  as  soon  as  we  have  introduced her  year  of  birth,  we  have  to 
  1424.   specifically ask 1-2-3 to recalculate the worksheet,  thus the {CALC}.  Please 
  1425.   do  not  forget to name Y14 with the name "physname",  and Y15 with  the  name 
  1426.   "operator".
  1427.  
  1428.        Next comes our last challenge for this session:
  1429.  
  1430.   Y16: '{GOTO}p12~/RIlmp~{?}
  1431.   Y17: '/XG\m~
  1432.   
  1433.        We have a new command (/RI) which means Range Input. We could have used a 
  1434.   similar  way to introduce the LMP of the patient,  as we did to introduce  her 
  1435.   birthday.  That would not have been very challenging however.  Beside patients 
  1436.   always  know  their birthday pretty well,  but are not usually so  sure  about 
  1437.   their  last menstrual periods "It was September 16,  no,  I think it  was  the 
  1438.   first of October." The entry system we used previously would not allow to loop 
  1439.   back to change a value. Of course we could have made a small modification such 
  1440.   as  "Do you want to change ?  Yes/No" and loop back,  but this would have been 
  1441.   outside the range of this tutorial.  So lets try a different method.  First go 
  1442.   in cell P10 and
  1443.  
  1444.   /Range Name Create LMP~ and define the range P10..U15
  1445.  
  1446.  
  1447.                                        22
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.   
  1454.  
  1455.  
  1456.   
  1457.        Then go in Q12 and issue the command:
  1458.  
  1459.   /Range Unprotect Q12~
  1460.   
  1461.        and do the same in cell S12 and U12. You will notice that these cells are 
  1462.   now in high intensity. What we have done by using the /Range input is define a 
  1463.   range  in which one can introduce number.  But since the cells  are  naturally 
  1464.   "protected"  (a  strange concept,  that I refer you to your manual  to  better 
  1465.   understand)  we need to /Range Unprotect some of them.  If you run it now  you 
  1466.   will see the result.  To do this go in cell Q2 and introduce the value 1, then 
  1467.   press <ALT M>,  and in the menu, select Name. This will allow you to debug any 
  1468.   problem so far. The most likely problem would be and error such as
  1469.  
  1470.                            Illegal cell or range name
  1471.  
  1472.        that would be displayed in the bottom left corner of the screen, with the 
  1473.   incriminated  cell or range on the second line on the top left of the  screen. 
  1474.   The likely error,  is that you forgot to define one of the ranges,  during one 
  1475.   of the /Range Name Create operation.  Fix the problem,  then go in cell Q2 and 
  1476.   introduce the value 1, then press <ALT M>, and in the menu, select Name to try 
  1477.   again.  When  you reach the LMP input range you will note that you can only go 
  1478.   in cells Q12, S12, and U12. What ever movements you use with the arrows cursor 
  1479.   you  will only be able to go in these cells,  and most of the  other  movement 
  1480.   keys  will  simply beep at you.  To escape just introduce the values that  you 
  1481.   want, then press return. You may have to press return twice, if you are making 
  1482.   an  entry at the same time.  The screen will then scroll and wait for  you  to 
  1483.   press an extra return,  before returning to the menu. This extra return is due 
  1484.   to  the  {?}  that we placed in Y16,  and it allows you  to  contemplate  your 
  1485.   masterpiece before moving onto the next subject.
  1486.  
  1487.        Now  that  you have master all these concepts the rest of this part  will 
  1488.   just be a breeze ! We will now fill the rest of the menu option except for the 
  1489.   Report option that will compose the next lesson.  Go back to the menu in  cell 
  1490.   Y5, and introduce:
  1491.  
  1492.   Z7: '/RIdata~/XG\m~
  1493.   
  1494.        This will introduce the data in the first screen. You will have to define 
  1495.   a "data" range that extends from:
  1496.  
  1497.   /Range Name Create data  and to the range limit question: A1..D8
  1498.   
  1499.        Again the /XG\m~ is designed to bring the user back in the menu,  when he 
  1500.   (she) has finished entering data.
  1501.  
  1502.        The next option we have to complete is:
  1503.  
  1504.   AA7: '{GOTO}a13~/RIinpcmts~/XG\m~
  1505.   
  1506.        Which  is  preparing the area for "free form" entry of comments that  the 
  1507.   user  might  want to include.  Again we have to define a range whose  name  is 
  1508.   inpcmts which is done by:
  1509.  
  1510.   /Range Name Create inpcmts    and to the range limit question: A13..B20
  1511.  
  1512.  
  1513.                                        23
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.   
  1520.  
  1521.  
  1522.   
  1523.        The next option on the menu is the report.  Since we will deal with  this 
  1524.   later,  lets  just temporarily introduce the following macro,  that just loops 
  1525.   back to the menu:
  1526.  
  1527.   AB7: '/XG\m~
  1528.   
  1529.        The  next option is also very simple.  We could /Range Erase every  field 
  1530.   that we had previously used (patname,  patfname,  physname etc..) but  besides 
  1531.   being  a lot of typing this would be much more time consuming than erasing big 
  1532.   blocks  of  data at a time.  So the following macro will clean  our  worksheet 
  1533.   faster:
  1534.  
  1535.   AC7: '/REjunk1~/REjunk2~/REybirth~/REjunk4~
  1536.   {GOTO}patname~1~/XG\m~
  1537.   
  1538.        Again the series of command is longer than 80 characters so I had to  cut 
  1539.   it in two.  BE VERY CAREFUL not to introduce any blank between the two part of 
  1540.   the line when reconstituting it. You will also have noticed in the second line 
  1541.   the [{GOTO}patname~1~] instruction. This is the answer to the second note that 
  1542.   you had to remind yourself.  We simply ask 1-2-3 to erase everything we do not 
  1543.   need,  than  to  go  in the cell that will contain  the  patient's  name,  and 
  1544.   introduce  our  test variable.  So you see that although this is a  few  extra 
  1545.   step,  we  do not have to care about them,  1-2-3 does them for us.  The range 
  1546.   that you have to define for 
  1547.  
  1548.   Junk1 is Q2..Q12
  1549.   Junk2 is S4..S12
  1550.   Junk4 is C6..D8
  1551.   
  1552.        Note  that these are more easy to define than the previous  one.  Why  no 
  1553.   Junk3  range ?  Well logically this would have been the range that would  have 
  1554.   erased  the year of birth of the patient.  Since this is only one cell and  it 
  1555.   already had a name, why not use it ?
  1556.  
  1557.        The final macro, to exit 1-2-3 is very simple:
  1558.  
  1559.   AD7: '/QYEY
  1560.   
  1561.        Note  that  if you have started from the Lotus Access Menu,  you will  be 
  1562.   returned  to  it,  and that there is no way to return  directly  to  DOS,  and 
  1563.   continue  in a batch file for instance.  Something like /QYEYEY (for Exit Yes) 
  1564.   will not work.  If you want to go to DOS, then you have to start with 123.EXE, 
  1565.   and not LOTUS.EXE.  This may look a trivial matter, but you might have in your 
  1566.   worksheet a menu that says something like:
  1567.  
  1568.   Do you want to go to WordStar  dBase  DOS  
  1569.  
  1570.   or whatever.  Under each of those choices you could have a macro that contains 
  1571.   instructions such as:
  1572.  
  1573.   /PFnext~ROOUML0~QRwordstar~GQ/QY
  1574.  
  1575.   /PFnext~ROOUML0~QRdbase~GQ/QY
  1576.  
  1577.  
  1578.  
  1579.                                        24
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588.        Which  means:  print  to a file called NEXT,  and  replace  the  existing 
  1589.   version by this one, using the option other unformated, with no left margin, a 
  1590.   range called WordStar that could contain something like:
  1591.  
  1592.   cd\wp
  1593.   ws
  1594.  
  1595.        as  you  note these are DOS commands.  That's why you have to print  them 
  1596.   with no left margin, and no header of course. Then the macro exits from 1-2-3, 
  1597.   and  you could get dumped into a previously running batch file that could  say 
  1598.   something like:
  1599.  
  1600.   cd\123
  1601.   123
  1602.   rename next.prn next.bat
  1603.   next
  1604.  
  1605.        and  would therefore start the next application,  without having to  know 
  1606.   anything about how you got there. Isn't that great ?
  1607.  
  1608.        It  might  be necessary to give at this point what the  expected  answers 
  1609.   should be if you input some values. To do that press <ALT M>, select Name, and 
  1610.   complete your screen to look like this:
  1611.  
  1612.  
  1613.  
  1614.         Patient's information:             01-Mar-85 <-- Today's Date
  1615.                    Last Name : Foucher
  1616.                   First Name : Adele
  1617.          Birthday (MM/DD/YY) :  5 / 4 / 56        28 <-- Patient's age
  1618.  
  1619.           Referring physician: Herodote
  1620.  
  1621.  
  1622.                      Operator: Vesalius
  1623.  
  1624.  
  1625.                LMP (MM-DD-YY):  9 / 6 / 84 06-Sep-84
  1626.           Nbr of days elapsed:                   176 days
  1627.          Nbr of weeks elapsed:                    25 weeks
  1628.          Due Date (from LMP) :             13-Jun-85
  1629.  
  1630.       Please move the cursor with the <-- and --> arrow
  1631.       When you have seen the age, type and extra <RETURN>
  1632.  
  1633.  
  1634.        Since you won't be able to introduce the same date as I included, add the 
  1635.   difference between the date that you enter and the sample date above,  to  the 
  1636.   patient's birthday,  and LMP.  (We hope that Victor Hugo,  will not resent the 
  1637.   use of his wife in this tutorial, if you do not like it, you can include Sally 
  1638.   Brown instead, but I did not wanted to get into copyright trouble with Schultz 
  1639.   !). Then select Data and fill the next screen:
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.                                        25
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.  
  1653.  
  1654.  
  1655.        D A T A   I N P U T   A R E A
  1656.        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       Predicted age   Predicted size
  1657.                               Data    Mean     in week           in mm
  1658.                              # 1 # 2        5th  50th 95th  5th  50th 95th
  1659.                                                                             ?
  1660.          Biparietal Diameter  66      66.0 |23.8 25.6 27.4 |  60   64   69 |0
  1661.            Abdominal Diam #1  55      55.0 |               |               |
  1662.            Abdominal Diam #2  53      53.0 |               |               |
  1663.        Abdominal Perimeter:  169
  1664.        Estimated Fetal Weight (g) -->  677 |               | 632  871 1193 |0
  1665.        EFW (pounds + ounces)   1 lbs.    8 ounces
  1666.  
  1667.        C O M M E N T S:
  1668.        ~~~~~~~~~~~~~~~~
  1669.  
  1670.  
  1671.        This  should  allow  you  to  check that  the  equations  that  you  have 
  1672.   introduced produce the correct value.  Although this may not be critical for a 
  1673.   tutorial,  a friend of yours might be pregnant,  and you wouln'dt want to give 
  1674.   her incorrect information should you demonstrate her this worksheet !
  1675.  
  1676.        The  last  macro  that we will introduce for this session is  the  dating 
  1677.   macro:
  1678.  
  1679.   Z2: '{GOTO}message~/DFdate~@TODAY~~~/XG\M~
  1680.  
  1681.        The  /DFdate~@TODAY~~~ portion tells 1-2-3 to /Data Fill a  range  called 
  1682.   "date",  with  the formula @TODAY,  and accept the increment and maximal limit 
  1683.   value. Then the macro initiate the menu system. The \0 is a particuliar macro, 
  1684.   that  is  executed automatically when the program is started,  but  cannot  be 
  1685.   invoqued after that.  It allows to store for you all sorts of chores that  you 
  1686.   would otherwise do manually, such as changing the default subdirectory etc...
  1687.  
  1688.  
  1689.  
  1690.  
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.                                        26
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.   4) Part IV: Word Processing with 1-2-3
  1721.  
  1722.        In the previous three sections we have prepared a sophisticated series of 
  1723.   instructions  that allows us to enter data concerning our patient,  and make a 
  1724.   series  of calculations based on these data.  We are going to prepare in  this 
  1725.   installment all the necessary instructions to have 1-2-3 prepare a report  out 
  1726.   of  these  data.  What  one  means with a  report  is  apparently  exceedingly 
  1727.   variable.  Most  data-base programs have "report" facilities that are in  fact 
  1728.   sorted  listing  of  subset of the original data.  These typically  look  like 
  1729.   columns of unattractive numbers. What we mean here by report is something that 
  1730.   should  attempt  to  duplicate what a secretary would send  to  the  referring 
  1731.   physician. We are (fortunately/unfortunately) not ready yet to be able to have 
  1732.   1-2-3  be  as  good as a real secretary,  but as you will  see,  we  can  make 
  1733.   noticeable effort in this direction.
  1734.  
  1735.        The first thing we will want the user to check before printing the report 
  1736.   is  that the printer is ON.  Since the number of instructions that we will  be 
  1737.   using is large,  and would otherwise mess up the clean menu we previously did, 
  1738.   we will start a new menu such as:
  1739.  
  1740.   Is the printer "ON" ?     Print the report
  1741.   
  1742.        A few important things here:  As you see, 1-2-3 allows to branch menus to 
  1743.   sub  menu.  This  is extremely convenient,  and allows to  make  fairly  user-
  1744.   friendly  applications.  Also,  note that the menu do not have to be spacially 
  1745.   contiguous.  We will see in a instant how to connect them.  Lets us  introduce 
  1746.   the following instructions:
  1747.  
  1748.   AH1: 'Is the printer "ON" ?
  1749.   AH2:  'Please  make  sure  that the printer is "ON",  then select  "Print  the 
  1750.   report"
  1751.   AI1: 'Print the report
  1752.   AI2: 'Please be patient, printing the report takes a few minutes !~
  1753.   
  1754.        Which corresponds to the entry of the menu,  and the previously described 
  1755.   line of explanation.  Also note that the menu options do not necessarily  need 
  1756.   to be a single word. A short sentence is perfectly valid, as long as the total 
  1757.   of all the entries does do exceed the length of the screen,  minus the command 
  1758.   indicator.  Note that here we place the "Is the printer "ON" " option first so 
  1759.   that if the user press return without too much thought, he does not bypass the 
  1760.   checking: we will simply make this entry loop back with the instruction on the 
  1761.   third line of the menu being:
  1762.  
  1763.   AH3: '/XMAH1~
  1764.   
  1765.        The  user has therefore to make a conscientious effort ot select the next 
  1766.   choice. This menu is unfortunately missing a crucial element. What if the user 
  1767.   decides that he want to modify a value ?  No way ! What we need to build in is 
  1768.   a  form of ESCAPE.  As you know when you are using a real 1-2-3 menu  you  can 
  1769.   always  press  ESC to back-up one step.  If you press ESC in a menu  that  you 
  1770.   create,  1-2-3  will simply dump you out of the menu.  For a trained user that 
  1771.   represent no problem,  but to make the menu more user friendly we have to come 
  1772.   with a better way than that.  The easiest is by far to include an  instruction 
  1773.   such as:
  1774.  
  1775.  
  1776.  
  1777.                                        27
  1778.  
  1779.  
  1780.  
  1781.  
  1782.  
  1783.  
  1784.  
  1785.  
  1786.   AJ1: 'Main Menu
  1787.   AJ2: 'Returns to the main menu
  1788.   AJ3: '/XG\m~
  1789.   
  1790.        that  does nicely the job.  When using such back looping option,  try  to 
  1791.   forecast  where the user might want to return.  If you have a very complicated 
  1792.   branching  pattern,  the user might not want to come all the way back  to  the 
  1793.   root of the tree of menu, and you may have to include more than one option for 
  1794.   back-looping.  This  system works perfectly,  but it has a major disadvantage: 
  1795.   each time you lose one of the possible options for your menu.  A neater trick, 
  1796.   but that does not work all the time is to introduce another instruction on the 
  1797.   line, that does the looping. For instance if we modify
  1798.  
  1799.   AH3: '/XMAH1~ 
  1800.   
  1801.        to become
  1802.  
  1803.   AH3: '/XMAH1~/XMmenu~
  1804.   
  1805.        then by pressing ESC,  1-2-3 abandon the first instruction (/XMAH1~)  and 
  1806.   continues processing at the second (/XMmenu~). We have indeed achieved what we 
  1807.   wanted: by pressing ESC, the user is backed up one level. The problem, is that 
  1808.   this  trick  only works consistently within menu,  and no as well  with  other 
  1809.   instruction  (/XL  for instance).  This is however one way to have  your  menu 
  1810.   mimic  very closely those of 1-2-3.  To summarize,  the general principle  is: 
  1811.   after the normal series of instructions, place a last instruction that returns 
  1812.   the user to the previous level.  Another problem, is that the user will not be 
  1813.   able  to  press ESC twice to back up two levels in the menu.  That would  also 
  1814.   drop him back in the worksheet.  Nevertheless this is a good trick,  that  you 
  1815.   should try to implement as much as you can.  Here is another example on how to 
  1816.   use it in the instruction for the printing option:
  1817.  
  1818.   AI3: '/REy35..ae100~/XGAH5~/XMAH1~
  1819.   
  1820.        Here we erase the range Y35..AE100 which is the location in which we will 
  1821.   prepare  the report,  then we go (/XG) to the rest of the printing instruction 
  1822.   that  are  located  in  cell AH5.  The program should  never  reach  the  last 
  1823.   instruction (/XMAH1~), and will only arrive there if the user press ESC during 
  1824.   execution of the beginning of the line.
  1825.  
  1826.        We are now ready to start the preparation of the report.  To  demonstrate 
  1827.   that  we  can  assemble the report out of little portion,  we  will  start  to 
  1828.   assemble the second paragraph, that we will later integrate in the text. 
  1829.  
  1830.        The  first task that we will assign us is to print a paragraph that  says 
  1831.   what is the estimated gestational age,  and when the baby is due. We know what 
  1832.   is the estimated gestational age from the BPD. We calculated this value in H6. 
  1833.   We  also  know when the baby is due.  We have stored this value in V15  (in  a 
  1834.   range called:  duedate).  However, the estimated age is expressed in weeks and 
  1835.   tenth of week.  That is surely not a standard unit !  The tenth of week should 
  1836.   therefore  be  converted in days.  Besides the due date are expressed  in  the 
  1837.   Lotus  Date 1 format,  which although is standard in Europe,  (and I was  told 
  1838.   with  the US Army),  is not traditionally accepted in correspondence.  We will 
  1839.   want to change that too. The result we want to obtain is something like:
  1840.  
  1841.  
  1842.  
  1843.                                        28
  1844.  
  1845.  
  1846.  
  1847.  
  1848.  
  1849.  
  1850.  
  1851.  
  1852.  
  1853.             The estimated gestational age is 15 weeks and 3 days, based on
  1854.        the BPD. The expected due date based on the LMP is May 12, 1985.
  1855.  
  1856.        We could have the text included in the macro (we will see example of that 
  1857.   later), but this is generally a less efficient solution. Instead, we will make 
  1858.   a  copy  of it in a range that we will call "estage" (for estimate  age)  that 
  1859.   will span B41..B45, so please /Range Name Create estage from B41..B45. We will 
  1860.   complete the entry in each of those cells by including the following:
  1861.  
  1862.   B41: "     The estimated gestational age is
  1863.   B42: @INT(H6)
  1864.   B43: 'weeks and
  1865.   B44: @INT((H6-B42)*7)
  1866.   B45: "days, based on the BPD.
  1867.   
  1868.        You  recognize  that @INT obtains the number of week  of  gestation,  and 
  1869.   transforms  the  decimal  portion (the number minus its integer)  in  days  by 
  1870.   multiplying  it  by  7.  We now would like to use the  almost  unused  command 
  1871.   called:
  1872.  
  1873.   /Range Justify
  1874.   
  1875.        and  justify  these five line into one normal sentence.  If you  try  it, 
  1876.   nothing will happen. Why ? Well 1-2-3 refuse to justify anything that contains 
  1877.   a  formula.  No problem,  we will calculate the values of  the  formulas,  and 
  1878.   transform  them into numbers.  Here we hit a first snag.  If we calculate  the 
  1879.   formula, we will have no problems, except that the second time around, when we 
  1880.   will want to use the formula,  it will have disappeared,  and be replaced by a 
  1881.   number !  That's not too great, if we have to retype the formula each type, we 
  1882.   might as well forget the whole worksheet !. What we can do to get around this, 
  1883.   is  copy  the  whole  range  "estage" into a temporary  range  that  we  could 
  1884.   calculate.  This is a nice and simple solution: the original formula are still 
  1885.   there,  and when we calculate the copied formula we do not mess the originals. 
  1886.   But here again we hit a snag. Try for instance to 
  1887.  
  1888.   /Copy estage~ to B50
  1889.   
  1890.        By  the way lets call B50 estage2 (so please /Range Name  Create  estage2 
  1891.   from  B50).  What happened ?  Well you noticed it:  both formula now refer  to 
  1892.   other cells than the one we wanted.  What is the problem ? In the formula that 
  1893.   we  defined  in  B42 and B44,  we use "relative reference"  and  not  absolute 
  1894.   reference, when we moved the formula the cell that are now referred to have no 
  1895.   interest  whatsoever  in our problem.  How to solve this last problem  ?  Easy 
  1896.   transform  the entries to absolute references by adding a $ sign in  front  of 
  1897.   the letter and number coordinated of the cell address:
  1898.  
  1899.   B42: @INT($H$6)
  1900.   B44: @INT(($H$6-$B$42)*7)
  1901.   
  1902.        Another problem solved. So now lets try to
  1903.  
  1904.   /Range Justify
  1905.   
  1906.        the copied range. Ok, now we have copied our range, but the justification 
  1907.  
  1908.  
  1909.                                        29
  1910.  
  1911.  
  1912.  
  1913.  
  1914.  
  1915.  
  1916.  
  1917.  
  1918.   still does not work on formula. So what we will do is transform these formulas 
  1919.   into values. Fortunately this problem is relatively minor. This is easily done 
  1920.   by going into the cell,  pressing EDIT, then CALC. We now have a value. So now 
  1921.   lets try again to
  1922.  
  1923.   /Range Justify
  1924.   
  1925.        What do we get ? Nothing ? Ha Ha, another problem: 1-2-3 not only refuses 
  1926.   to  justify  text that includes formula,  it also refuse to justify text  that 
  1927.   contains values. Fortunately this problem is relatively minor. What we need it 
  1928.   to transform a value into a label. This is easily done by going into the cell, 
  1929.   pressing EDIT, then HOME and adding an apostrophe before pressing return. This 
  1930.   may  sound terribly difficult,  and it is indeed terribly tedious to  do,  but 
  1931.   remember that now we are merely finding out what we will have to instruct 1-2-
  1932.   3 to do. Once this is written into a macro, than it will be a breeze.
  1933.  
  1934.        We  are  now ready to write the first line of our macro.  For  reason  of 
  1935.   space  I  had to split it on two line.  Please be careful not to  include  ANY 
  1936.   blank space between the two segments of the line
  1937.  
  1938.   AH5: '{GOTO}estage2~/Cestage~~{DOWN}{EDIT}{CALC}{HOME}'{DOWN}{DOWN}
  1939.   {EDIT}{CALC}{HOME}'{END}{DOWN}
  1940.   
  1941.        You will see that virtually all book about 1-2-3 advise you to split long 
  1942.   macros  so  that you can see the whole thing on one screen.  That  is  a  nice 
  1943.   advice,  but often quite impractical. The macro that we will develop her would 
  1944.   be  so  long that it would in turn be impractical to read,  besides  it  would 
  1945.   produce a lengthy downward extension in an otherwise compact worksheet,  which 
  1946.   would dramatically increase the memory requirements.  Finally when you include 
  1947.   a  IF condition (/XI) in a line,  1-2-3 expects the next line to correspond to 
  1948.   the action to be taken when the condition is not fulfilled, and splitting line 
  1949.   would therefore not work.
  1950.  
  1951.        The next line in our macro is:
  1952.  
  1953.   AH6: '{DOWN}The expected due date based on the LMP is
  1954.   {DOWN}@month(duedate)~{EDIT}{CALC}~
  1955.   /RNDmonthdue~/RNCmonthdue~~/XCmonth?~{DOWN}
  1956.   
  1957.        which  includes a fair number of new concepts.  The @month is  a  formula 
  1958.   that  finds the month value out of a date (duedate).  You are by now  familiar 
  1959.   with the {EDIT}{CALC}~ trick. Since we want to convert the number of the month 
  1960.   into a word (June is this case) we have to invoke a subroutine to do that. Why 
  1961.   not  a @VLOOKUP formula ?  Because 1-2-3 is not able to deal with alphanumeric 
  1962.   character  in such tables,  and only numbers are  accepted.  @CHOOSE,  another 
  1963.   poorly documented formula, would not work for the same reasons. So will invoke 
  1964.   a subroutine by using a subroutine call:  /XR.  The subroutine is  essentially 
  1965.   going  to  compare a value.  If the comparison is false it will test the  next 
  1966.   value  on the next line,  otherwise it will enter in the cell the name of  the 
  1967.   month. Each line ends by a subroutine return (/XR~).
  1968.  
  1969.    MONTH?
  1970.    /XImonthdue=1~January~/XR~
  1971.    /XImonthdue=2~February~/XR~
  1972.    /XImonthdue=3~March~/XR~
  1973.  
  1974.  
  1975.                                        30
  1976.  
  1977.  
  1978.  
  1979.  
  1980.  
  1981.  
  1982.  
  1983.  
  1984.    /XImonthdue=4~April~/XR~
  1985.    /XImonthdue=5~May~/XR~
  1986.    /XImonthdue=6~June~/XR~
  1987.    /XImonthdue=7~July~/XR~
  1988.    /XImonthdue=8~August~/XR~
  1989.    /XImonthdue=9~September~/XR~
  1990.    /XImonthdue=10~October~/XR~
  1991.    /XImonthdue=11~November~/XR~
  1992.    /XImonthdue=12~December~/XR~
  1993.  
  1994.        Let us introduce this:
  1995.  
  1996.   AC18: 'MONTH?
  1997.   AC19: '/XImonthdue=1~January~/XR~
  1998.   AC20: '/XImonthdue=2~February~/XR~
  1999.   AC21: '/XImonthdue=3~March~/XR~
  2000.   AC22: '/XImonthdue=4~April~/XR~
  2001.   AC23: '/XImonthdue=5~May~/XR~
  2002.   AC24: '/XImonthdue=6~June~/XR~
  2003.   AC25: '/XImonthdue=7~July~/XR~
  2004.   AC26: '/XImonthdue=8~August~/XR~
  2005.   AC27: '/XImonthdue=9~September~/XR~
  2006.   AC28: '/XImonthdue=10~October~/XR~
  2007.   AC29: '/XImonthdue=11~November~/XR~
  2008.   AC30: '/XImonthdue=12~December~/XR~
  2009.   
  2010.        and give it the name:  "month?".  Note that "?",  is a valid character in 
  2011.   range name.
  2012.  
  2013.        We do not need any error trapping here since the value is derived from  a 
  2014.   date  computed  by  1-2-3.  Note however that we will compare a  range  called 
  2015.   "monthdue",  and  that  we  therefore need to name this  range.  It  would  be 
  2016.   tempting to /Range Name cell B51 with the name "monthdue". That would not work 
  2017.   however.  In a few minutes we will /Range Justify this range.  Now, when 1-2-3 
  2018.   Justifies  a range,  it loses not only its boundaries (which makes sense)  but 
  2019.   also it left upper corner and sometimes its name (which does not make  sense). 
  2020.   Therefore  we  have to have the macro create the name on the  spot:  thus  the 
  2021.   /RNCmonthdue~~ (note the TWO ~,  one to accept the name,  the second to accept 
  2022.   the current cell). That would be quite simple, however, occasionally the range 
  2023.   name  might not have been destroyed,  but simply stretched,  often to  include 
  2024.   cell  IV2048 !  It is therefore a good precaution to start by deleting a  name 
  2025.   that you want to create.  This too has a small problem: the first time around, 
  2026.   the range will not be there to be erased,  and you therefore have to include a 
  2027.   dummy  range somewhere that you will call "monthdue".  Please do that in  AJ34 
  2028.   for instance.
  2029.  
  2030.        We  have  now  found  the month,  and transformed it  into  a  word  that 
  2031.   represent the name of the month.  We now want to get the day and the year. The 
  2032.   next line in the macro will be:
  2033.  
  2034.   AH7: '@day(duedate)~{EDIT}{CALC}{HOME}'{END}, 19{DOWN}
  2035.   @year(duedate)~{EDIT}{CALC}{HOME}'~
  2036.   {UP}/RJ.{DOWN}~{EDIT}.{LEFT}{LEFT}{LEFT}{BS}~
  2037.   
  2038.        The  @day(duedate)~{EDIT}{CALC}{HOME}'{END},  19{DOWN}  portion  is  self 
  2039.  
  2040.  
  2041.                                        31
  2042.  
  2043.  
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.  
  2050.   explanatory:  @DAY extracts the value of the day out of monthdue. Note that to 
  2051.   use  a  new  formula we had to go to the next  line.  The  {EDIT}{CALC}{HOME}' 
  2052.   transforms  the formula into a value,  and then into a label to  which  {END}, 
  2053.   19{DOWN} adds a comma,  a blank space and the value 19. The macro them goes in 
  2054.   the  next cell to get the year value of duedate @year(duedate)~ and then  does 
  2055.   the same kind of editing: {EDIT}{CALC}{HOME}'~.
  2056.  
  2057.        It  is  worth noticing that 1-2-3 does not return the century portion  of 
  2058.   the year,  only the year itself, which is why we had to add it in the previous 
  2059.   line. We now have the value of our date, but it looks terrible. 
  2060.  
  2061.   B50: "     The estimated gestational age is
  2062.   B51: '25
  2063.   B52: 'weeks and
  2064.   B53: '4
  2065.   B54: "days, based on the BPD.
  2066.   B55: 'The expected due date based on this gestational age is
  2067.   B56: 'June
  2068.   B57: '13, 19
  2069.   B58: '85
  2070.   
  2071.  
  2072.        A little creative justification will fix this in a second. {UP} moves the 
  2073.   cursor one line up,  on the day line, (/RJ) justifies the range extending from 
  2074.   the anchored point (.) down {DOWN}~ one line. 
  2075.  
  2076.   B55: 'The expected due date based on this gestational age is
  2077.   B56: 'June
  2078.   B57: '13, 19 85
  2079.   
  2080.        We  can now edit this cell {EDIT},  add a period at the end of  the  date 
  2081.   (.),  then  move  3 to the left {LEFT}{LEFT}{LEFT} and remove {BS}  the  blank 
  2082.   space between 19 and 85.
  2083.  
  2084.   B55: 'The expected due date based on the LMP is
  2085.   B56: 'June
  2086.   B57: '13, 1985.
  2087.   
  2088.        Our  whole text is now there,  and it is now a simple matter to rejustify 
  2089.   it. To do so, introduce the next line:
  2090.  
  2091.  
  2092.   AH8: '{END}{UP}/RJ{END}{DOWN}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}
  2093.   {RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}~/RNCestage2~.{END}{DOWN}~
  2094.   
  2095.        again do not forget there should not be any blank between the two segment 
  2096.   of  line.  We  will start the justification at the upper left  corner  of  the 
  2097.   range.  The fastest way to get there is to press {END}{UP} which will leave us 
  2098.   at  the  interface between a filled and an empty cell.  We then issue the  /RJ 
  2099.   command,  and define the depth of the range we want to use by using END  DOWN, 
  2100.   then  we define the lateral extend of the range with a series of {RIGHT}.  The 
  2101.   number  of {RIGHT} is to compensate for the number of column that we  have  in 
  2102.   the  first  screen.  When you type those {RIGHT},  you will soon realize  that 
  2103.   Lotus could have abbreviated it into {->} or {R} !  If you have  ProKey,  this 
  2104.   will be easier. Note that again, the /Range Justify, has delete the range name 
  2105.  
  2106.  
  2107.                                        32
  2108.  
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.   "estage2", and that we have to recreate it, and define its extend.
  2117.  
  2118.        We  have now prepared the first paragraph,  and have covered most of  the 
  2119.   concept  that we will need for the rest of the text.  Let us go to the body of 
  2120.   the letter and start creating it.
  2121.        
  2122.  
  2123.   AH9: "{GOTO}y41~To Dr{DOWN}/Cphysname~~{UP}/RJ{RIGHT}{RIGHT}{DOWN}~{RIGHT}
  2124.   {RIGHT}{RIGHT}{UP}{UP}{UP}{UP}{UP}{UP}" Examination performed on {RIGHT}
  2125.   {RIGHT}{RIGHT}@month(date)~/RNDmonthdue~/RNCmonthdue~~/XCmonth?~{DOWN}
  2126.   
  2127.        and in
  2128.  
  2129.   AH10: '@day(date)~{EDIT}{CALC}{HOME}'{END}, 19{DOWN}@year(date)~{EDIT}
  2130.   {CALC}{HOME}'~{UP}{UP}/RJ.{DOWN}{DOWN}{RIGHT}{RIGHT}~{EDIT}.{LEFT}
  2131.   {LEFT}{LEFT}{BS}~{DOWN}{DOWN}
  2132.   
  2133.        Note that for the first time I refer in a macro,  to a cell address  with 
  2134.   it coordinate (Y41) and not through a range name. This is sometime useful when 
  2135.   you  are sure that something in your macro should never be moved around,  will 
  2136.   not enter in a formula... and especially when the cell will be part of a range 
  2137.   that will be justified. This avoid the constant renaming of the cell. The rest 
  2138.   of the line is fairly simple: we have 1-2-3 type the addressee: To Dr, then on 
  2139.   the  next line we copy the name of the addressee,  justify the whole think  to 
  2140.   put  it  back  on one line,  then we move to the right  and  up.  Again  1-2-3 
  2141.   introduce  a  label  for  us [" Examination performed  on  ]  which  is  right 
  2142.   justified by its prefix (").  We then reproduce (in cell AH10) our little date 
  2143.   arithmetic  that we previously used.  This explains the reason to use a /XC to 
  2144.   call a subroutine for the month. Otherwise we would have had to introduce this 
  2145.   series of code twice.  (Which would not have been a real big deal in  fact:  a 
  2146.   /Copy would have worked quite nicely, since we were careful to use range name, 
  2147.   and not cell addresses).
  2148.  
  2149.        We then introduce the next lines of instructions:
  2150.  
  2151.   AH11: '{LEFT}"Re:{RIGHT}/Cpatinfo~~{GOTO}ae39~/XIq4=0~ ~/XGreport1~
  2152.   AH12: '+birthday~{EDIT}{CALC}{HOME}'{END} years old~
  2153.   
  2154.        We again ask 1-2-3 to type something for us:  ["Re:] and copy in the next 
  2155.   cell  the patient's information "patinfo".  If you haven't defined this  range 
  2156.   yet  do  it by /RNC patinfo  Q2..Q4.  Here again we refer to a  specific  cell 
  2157.   (AE39) which is easier, then using a range name. Then we test if Q4 is = to 0. 
  2158.   If  it  is we introduce a blank (the blank between the two ~) which erase  the 
  2159.   display  of  the cell by concealing it behind a blank space.  We  then  go  to 
  2160.   "report1" which is the name of the cell where execution should proceed.  If Q4 
  2161.   is  not equal to 0,  then we copy onto this cell the value birthday (which  is 
  2162.   the age of the patient),  transform it into a number, than a label, then go to 
  2163.   the end of the label and add "years old".
  2164.  
  2165.        Lets introduce the next line:
  2166.  
  2167.   AH13: '{GOTO}Y41~{DOWN}{DOWN}{DOWN}{DOWN}Dear Dr{DOWN}/Cphysname~~{EDIT},
  2168.   {UP}/RJ{RIGHT}{RIGHT}{RIGHT}{RIGHT}{DOWN}{DOWN}~
  2169.   
  2170.        Nothing new here: we define a cell address, go to it, and do the same old 
  2171.  
  2172.  
  2173.                                        33
  2174.  
  2175.  
  2176.  
  2177.  
  2178.  
  2179.  
  2180.  
  2181.  
  2182.   trick  of  copying  a range,  and reformating it.  This cell should  be  named 
  2183.   "report1" as you had guessed.
  2184.  
  2185.   AH14: '{DOWN}{DOWN}{DOWN}'     Thank you for referring to us Ms{DOWN}
  2186.   /Cpatname~~{DOWN}/Cpatfname~~{EDIT} ~{DOWN}
  2187.   
  2188.        Here we have another little trick.  Note the /Cpatfname~~{EDIT}  ~{DOWN}. 
  2189.   Since it is likely that sometime the user might be lazy, and not introduce the 
  2190.   first name of the patient,  we have to plan for such circumstance.  If we were 
  2191.   to  leave a empty cell,  when we will later use the END UP trick to define the 
  2192.   range to justify,  the pointer would stop at this level, since it will find an 
  2193.   empty cell.  This would thus be too early, and crash the macro. By introducing 
  2194.   an additional blank space, we fill the cell with something invisible, but that 
  2195.   1-2-3 will recognize as a "filled" cell.  The only inconvenient,  is that  the 
  2196.   first  name of the patient will be followed by two blank and not one,  but  we 
  2197.   had admitted that we would not be as perfect as a real secretary !
  2198.  
  2199.   AH15: 'who is currently{DOWN}/Cage~~{EDIT}{HOME}@INT~{EDIT}{CALC}{HOME}'
  2200.   {DOWN}weeks by dates.
  2201.   
  2202.        Here we have another little trick. When we copy age, we copy the formula: 
  2203.   +($V$13/7).  A minor bug of 1-2-3 if that if we /Copy it, we get the format of 
  2204.   the  cell  together,   and  therefore  not  the  numbers  behind  the  period. 
  2205.   Unfortunately, when we EDIT CALC it, they reappear. To get rid of them we need 
  2206.   to use {EDIT}{HOME}@INT~ which gives us the integer of the formula. We did not 
  2207.   used  the  integer  previously because we wanted the full  precision  for  our 
  2208.   computations.
  2209.  
  2210.        The  next cell does not poses any challenge anymore.  We can now  justify 
  2211.   this paragraph by:
  2212.  
  2213.   AH16: '{UP}{UP}{END}{UP}/RJ.{END}{DOWN}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}
  2214.   {RIGHT}{RIGHT}~
  2215.  
  2216.   AH17: '{END}{DOWN}{DOWN}{DOWN}
  2217.   
  2218.        then copy the product of our earlier efforts:
  2219.  
  2220.   AH18: '/Cestage2~~{END}{DOWN}{DOWN}{DOWN}
  2221.   
  2222.        Note  the  {END}{DOWN}{DOWN}{DOWN} that is a way to find the end  of  the 
  2223.   paragraph, then pass one line, and position the pointer to the next line to be 
  2224.   ready to proceed with the next set of instructions.
  2225.  
  2226.        The next two lines offer few challenges:
  2227.  
  2228.   AH19: '     The estimated fetal weight (EFW) is{DOWN}/Cefw~~
  2229.   AH20: '{EDIT}{CALC}{HOME}'{DOWN}grams (which is about{DOWN}/Clbwgt~~{EDIT}
  2230.   {CALC}{HOME}'{DOWN}pounds and {DOWN}/Cozwgt~~{EDIT}{CALC}{HOME}'{DOWN}
  2231.   ounces).{DOWN}
  2232.   
  2233.        we  again have the now familiar trick of /Crange~~,  remember the two  ~, 
  2234.   one to terminate the name of the range,  the second to accept the current cell 
  2235.   as  the recipient.  The copied value is then  {EDIT}{CALC}{HOME}'{DOWN}.  Note 
  2236.   that  it is not necessary to press return (~) after the  apostrophe,  pressing 
  2237.  
  2238.  
  2239.                                        34
  2240.  
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.   {DOWN}  is  sufficient.  You will notice later on that if you were to use  the 
  2249.   formula as they are,  you would not obtain the expected value,  although  they 
  2250.   are correct in the worksheet. What happened ? As in previous cases, by copying 
  2251.   the  formula you in fact change the cells that the formula refer to,  and  the 
  2252.   formula loses in meaning.  As before the solution is to transform the formulas 
  2253.   in  the original cell to indicate absolute references.  So you should  correct 
  2254.   the formula on the next few lines to their new values on the second line. This 
  2255.   merely involve adding plenty of $ signs !
  2256.  
  2257.   change:
  2258.   E6: @IF(@ISERR(@IF(@AVG(C6..D6) <105,@AVG(C6..D6),@ERR)),0,@AVG(C6..D6))
  2259.   into:
  2260.   E6: @IF(@ISERR(@IF(@AVG($C$6..$D$6) <105,@AVG($C$6..$D$6),@ERR)),0,
  2261.   @AVG($C$6..$D$6))
  2262.  
  2263.  
  2264.   change:
  2265.   E10:@IF(BPD=0#OR#E7=0#OR#E8=0,@FALSE,
  2266.   @ROUND((10^(-1.7492+0.166*(BPD/10) + 
  2267.   0.046*(ABD_PER/10)-2.646*((ABD_PER/10)*(BPD/10))/1000))*1000,0))
  2268.   into:
  2269.   E10:@IF($BPD=0#OR#$E$7=0#OR#$E$8=0,@FALSE,
  2270.   @ROUND((10^(-1.7492+0.166*($BPD/10) + 
  2271.   0.046*($ABD_PER/10)-2.646*(($ABD_PER/10)*($BPD/10))/1000))*1000,0))
  2272.  
  2273.   change:
  2274.   C11: @INT(EFW/453)
  2275.   into:
  2276.   C11: @INT($EFW/453)
  2277.  
  2278.   change:
  2279.   E11: @ROUND((EFW-LBWGT*453)/28,0)
  2280.   into:
  2281.   E11: @ROUND(($EFW-$LBWGT*453)/28,0)
  2282.  
  2283.   change:
  2284.   V15: (D1) @IF(@ISERR(LMPDATE),@ERR,@IF(@ISERR(V13),@ERR,LMPDATE+280))
  2285.   into:
  2286.   V15: (D1) @IF(@ISERR($LMPDATE),@ERR,@IF(@ISERR($V$13),@ERR,$LMPDATE+280))
  2287.  
  2288.   change:
  2289.   L6: @IF(AGE=0,0,-19.634+3.0209*AGE+0.042134*AGE^2-0.0011756*AGE^3)
  2290.   into:
  2291.   L6: @IF($AGE=0,0,-19.634+3.0209*$AGE+0.042134*$AGE^2-0.0011756*$AGE^3)
  2292.  
  2293.   change:
  2294.   L10: @IF(AGE<15,0,10^(0.5328769+0.1122225*AGE-0.000145731*AGE^2
  2295.   -0.0000202932*AGE^3))
  2296.   into:
  2297.   L10: @IF($AGE<15,0,10^(0.5328769+0.1122225*$AGE-0.000145731*$AGE^2
  2298.   -0.0000202932*$AGE^3))
  2299.  
  2300.   change:
  2301.   K10:@IF(L10=0#OR#AGE<15,0,L10-(10^(-2.72529+0.4042264*AGE-
  2302.   0.01048152*AGE^2+0.000098495*AGE^3)))
  2303.  
  2304.  
  2305.                                        35
  2306.  
  2307.  
  2308.  
  2309.  
  2310.  
  2311.   
  2312.  
  2313.  
  2314.   into:
  2315.   K10:@IF($L$10=0#OR#$AGE<15,0,$L$10-(10^(-2.72529+0.4042264*$AGE-
  2316.   0.01048152*$AGE^2+0.000098495*$AGE^3)))
  2317.  
  2318.   change:
  2319.   M10:@IF(L10=0#OR#AGE<15,0,L10+(10^(-2.573974+0.4008528*AGE-
  2320.   0.01031992*AGE^2+0.0000961377*AGE^3)))
  2321.   into:
  2322.   M10:@IF($L$10=0#OR#$AGE<15,0,$L$10+(10^(-2.573974+0.4008528*$AGE-
  2323.   0.01031992*$AGE^2+0.0000961377*$AGE^3)))
  2324.  
  2325.   change:
  2326.   O10: @IF(EFW=0,0,@IF(EFW=0#OR#HIGHEFW=0,0,@IF(EFW<LOWEFW#OR#EFW>HIGHEFW,1,0)))
  2327.   into:
  2328.   O10: @IF($EFW=0,0,@IF($EFW=0#OR#$HIGHEFW=0,0,
  2329.   @IF($EFW<$LOWEFW#OR#$EFW>$HIGHEFW,1,0)))
  2330.   
  2331.        The next two lines will test whether the estimated fetal weight is normal 
  2332.   or not:
  2333.  
  2334.   AH21: '/XIefw<lowefw~The estimated fetal weight indicated that the 
  2335.   fetus is too small.~/XGreport2~
  2336.  
  2337.   AH22: '/XIefw>highefw~The estimated fetal weight indicated that the 
  2338.   fetus is too large.
  2339.   
  2340.        Exceptionally,  there  should  be a blank space at the end of  the  first 
  2341.   segment of the line when you reconstruct it.  Note that the first line ends by 
  2342.   [/XGreport2~].  This means that if the condition is true,  the line of text is 
  2343.   accepted, entered in the current cell, and that processing resume (/XG) at the 
  2344.   cell called "report2". If the condition is false, than the next line (AH22) is 
  2345.   executed.  Here  we  do not need to send the processing to a  special  address 
  2346.   after  testing.  Either the condition is true,  and the line is accepted,  and 
  2347.   then processing follows on the next line,  or the condition is false, the line 
  2348.   is not accepted, and processing follows at the next line anyway. The next line 
  2349.   will in fact justify the current paragraph, and is:
  2350.  
  2351.   AH23: '{UP}{END}{UP}/RJ{END}{DOWN}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}
  2352.   {RIGHT}~
  2353.  
  2354.   AH24: '{END}{DOWN}{DOWN}{DOWN}
  2355.   
  2356.        Again, you should 
  2357.  
  2358.   /Range Name Create report2 for cell AH23.
  2359.   
  2360.        We can now copy the comments that have been introduced:
  2361.  
  2362.   AH25: '/Ccomment~~/RJ.{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{RIGHT}{RIGHT}
  2363.   {RIGHT}{RIGHT}{RIGHT}{RIGHT}{RIGHT}~
  2364.   
  2365.  
  2366.        The range "comment" is smaller than the range "inpcmts".  Indeed,  we  do 
  2367.   not  want  to  copy  the title COMMENT in our final  report.  Go  name  (/RNC) 
  2368.   "comment" from B15..B20.
  2369.  
  2370.  
  2371.                                        36
  2372.  
  2373.  
  2374.  
  2375.  
  2376.  
  2377.  
  2378.  
  2379.  
  2380.  
  2381.        This last line (AH25),  offers no difficulty,  however,  note that we did 
  2382.   not  use the previously described trick of using END DOWN to define the  depth 
  2383.   of  the range.  Why ?  To use END DOWN to define the depth of the  range,  the 
  2384.   range ought to be at least 2 lines deep. If it is only one line deep, than END 
  2385.   DOWN  will bring you to the end of the worksheet,  not what you want to do  of 
  2386.   course.   To  avoid  that  pitfall we define ahead of time  what  we  want  to 
  2387.   justify.  We  now the size of the incoming range,  we defined it  earlier.  It 
  2388.   might  be tempting to justify a range that is the same size.  But as you know, 
  2389.   1-2-3  allows to introduce long labels that are longer than a screen,  and  an 
  2390.   advanced user that has notice that, might include in the range labels that are 
  2391.   longer,  and  could  not  be justified within the same  number  of  lines.  We 
  2392.   therefore have to exceed the area to be covered by the new range, to take this 
  2393.   into account.  After this justification, we are ready to move down to copy the 
  2394.   closing remarks.  We have up to now used the {END}{DOWN}{DOWN}{DOWN}  sequence 
  2395.   to do so. Since we do not know whether there will be a paragraph of comment or 
  2396.   not,  the way to do is to go many lines down first, then, find the last [empty 
  2397.   cell - filled cell] interface and move then two lines down:
  2398.  
  2399.   AH26: '{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}
  2400.   {DOWN}{END}{UP}{DOWN}{DOWN}
  2401.   
  2402.        This  insures  that with or without a paragraph of comment,  the  closing 
  2403.   remarks will be correctly spaced. We can then copy the closing remarks:
  2404.  
  2405.   B33: '     Sincerely yours,
  2406.   
  2407.        This would be conveniently stored in B33,  out of sight. Again you should 
  2408.   name this range:
  2409.  
  2410.   /Range Name Create closing for cell B33
  2411.   
  2412.        We are now ready to introduce the closing remarks in  the letter:
  2413.  
  2414.   AH27: '/Cclosing~~{DOWN}{DOWN}{DOWN}{DOWN}{DOWN}
  2415.   
  2416.        and  finish by introducing the operator,  in the correct position  for  a 
  2417.   signature:
  2418.  
  2419.   AH28: '{RIGHT}{RIGHT}{RIGHT}{RIGHT}/Coperator~~
  2420.  
  2421.        Our letter is now finally finished. We only have to define the range that 
  2422.   contains the letter, to be able to later print it. We could of course define a 
  2423.   fixed range of 58 lines,  starting just above the very first line that we used 
  2424.   in the letter:  Examination performed on "date". Although this would work, let 
  2425.   us define a more sophisticated approach.  The fixe range risks to crash if the 
  2426.   user has introduced an unusual amount of comment,  and has spilled over the 58 
  2427.   lines  limits onto the next page.  It would be embarrassing that our  program, 
  2428.   ignore such cases !  The way around it to start the range at an address we now 
  2429.   is  fix,  Y35  for instance,  then use something like END DOWN to  extend  the 
  2430.   range. Unfortunately, as you know, all the text that we have introduced in the 
  2431.   body  of  the  letter,  are just "long label" that are anchored  in  the  left 
  2432.   column, and are not "in" the adjacent cells. The cells on the right are indeed 
  2433.   empty.  The only cell that is not empty,  is the one that contains the name of 
  2434.   the operator.  Ha Ha, it was not by chance that we placed it there ! We can in 
  2435.  
  2436.  
  2437.                                        37
  2438.  
  2439.  
  2440.  
  2441.  
  2442.  
  2443.  
  2444.  
  2445.  
  2446.   fact start to define the range at Y35,  anchor the pointer, move a few cell to 
  2447.   the  right,  in  fact exactly the correct amount to reach the same  column  in 
  2448.   which the signature is stored, then plunge downward with a END DOWN command:
  2449.  
  2450.  
  2451.   AH29: '{GOTO}y35~/RNCletter~{BS}.{RIGHT}{RIGHT}{RIGHT}{RIGHT}{END}{DOWN}
  2452.   {RIGHT}{RIGHT}~
  2453.   
  2454.        The  {BS} is there to refuse the default range that 1-2-3 will suggest us 
  2455.   when  we give him the name of the range.  This trick is nice,  but there is  a 
  2456.   potential pitfall !  This trick rely crucially on the presence of something in 
  2457.   the  cell  that contains the name of the operator !  If the  user  forgot  (or 
  2458.   neglect) to introduce it,  that's it,  the macro crashes. As you remember, the 
  2459.   operator name was introduce by the instruction
  2460.  
  2461.   Y15: '{GOTO}p9~/XLOperator:~operator~
  2462.   
  2463.        We  are therefore sure that the user will have seen the message,  but how 
  2464.   about if he simply pressed return,  no label would be stored in the cell.  Now 
  2465.   you remember from our discussion that there is no way to trap an empty message 
  2466.   in  a /XL command.  Another trick that we previously used,  preloading a  cell 
  2467.   with  something  - a blank space would be sufficient here -,  would  not  work 
  2468.   either,  since by pressing return,  the user would erase the blank space,  and 
  2469.   empty the content of the cell.  The solution is then to add a blank after  the 
  2470.   signature  has  been  copied.  For  that let us modify the  previous  line  of 
  2471.   instruction to read:
  2472.  
  2473.   change:
  2474.   AH28: '{RIGHT}{RIGHT}{RIGHT}{RIGHT}/Coperator~~
  2475.   
  2476.   into:
  2477.   AH28: '{RIGHT}{RIGHT}{RIGHT}{RIGHT}/Coperator~~{EDIT} ~
  2478.   
  2479.        Which  place  the blank space after the operator's name.  If there  is  a 
  2480.   name,  it  will go unnoticed,  if there is nothing,  the blank space  will  be 
  2481.   sufficient to stop the END DOWN command.
  2482.  
  2483.        We  have  now solved all our problems and are ready to print our  letter. 
  2484.   Before  that,  I  can't resist giving a last final trick for all  of  you  out 
  2485.   there,  that  print  long report concerning First  Trimester  balance,  Second 
  2486.   Trimester balance,  Third Trimester balance,  and so on. You know that you can 
  2487.   include in the header, and footer, all sorts of information, but not the value 
  2488.   of a cell in the worksheet. This must have irritated quite a few people. 1-2-3 
  2489.   allows to include labels stored in the worksheet as title for graph labelling, 
  2490.   but not in the header ! Well here is a simple way to do that.
  2491.  
  2492.   AH30: '/Cpatname~nametitle~
  2493.   AH31: '/PPCAAOHPatient:
  2494.   AH32: '
  2495.   AJ32: '!This line should remain!
  2496.   AH33: '~ML1~~R80~OFQ
  2497.   
  2498.        What  this says is essentially:  copy the value stored in a range in  the 
  2499.   worksheet into another range. This second range here will be "nametitle" which 
  2500.   is  in  AH32.  Nothing  secret up to now.  Then  comes  /PPCAAOHPatient:  that 
  2501.  
  2502.  
  2503.                                        38
  2504.  
  2505.  
  2506.  
  2507.  
  2508.  
  2509.  
  2510.  
  2511.  
  2512.   essentially  means:  Print  to Printer after Clearing  All  previous  printing 
  2513.   conditions  previously  used,  then Align the form,  use Other conditions  and 
  2514.   include  a Header that contains (left justified) the  text:Patient.  Now  here 
  2515.   come  the trick.  As you know 1-2-3 can read labels that follows each other on 
  2516.   adjacent cells,  as long as the next cell is situated in the cell just  below. 
  2517.   Even  better  you  could even dream of splitting a command  on  to  line.  For 
  2518.   instance
  2519.  
  2520.   {DO
  2521.   WN}
  2522.   
  2523.        would work perfectly as well as:
  2524.  
  2525.   {DOWN}
  2526.   
  2527.        Now  no  one  with any sense would ever cut a single instruction  on  two 
  2528.   levels like that, except that in our case, it fits perfectly what we need: the 
  2529.   first portion remains constant,  than we can introduce a variable that will be 
  2530.   included in the header.  AJ32:  '!This line should remain!  Simply reminds you  
  2531.   not to compress the next line onto this one, which would result in erasing the 
  2532.   next  line  of  command,   when  the  name  is  copied  onto  it.   The  rest, 
  2533.   [~ML1~~R80~OFQ] starts by entering the name with a ~, then defines the correct 
  2534.   margins, and quit the submenu to return to the main printing menu. Then:
  2535.  
  2536.   AH34: 'Rletter~GPQ/XG\m~
  2537.   
  2538.        prints the letter (G),  sends a page advance command (P),  and returns to 
  2539.   the menu that we designed earlier.
  2540.  
  2541.        In  fact a very similar trick can be designed to automatically  save  the 
  2542.   worksheet  under a name stored in a cell from the worksheet.  The macro should 
  2543.   however check that the name follows the requirements of DOS filenames.
  2544.  
  2545.        I have included on the next page a sample of the type of printout that we 
  2546.   can obtain.  As you can see,  it is fairly decent, and it is a pity that 1-2-3 
  2547.   word-processing  abilities are so underutilized.  It is of course  tedious  to 
  2548.   prepare the printing macro,  but once it is done it can be used multiple time, 
  2549.   and  that saves a lot of time.  Besides,  once the general principles involved 
  2550.   are understood, we basically do the same things over and over.
  2551.  
  2552.        We have now toured most the advanced features of 1-2-3.  You now deserve, 
  2553.   to sit back,  and enjoy the model that you have create,  and admire the macros 
  2554.   at  work.  I hope that this has tought you some tricks that will be useful  in 
  2555.   your own worksheets. 
  2556.  
  2557.        Sincerely yours,
  2558.  
  2559.  
  2560.  
  2561.                                                Philippe Jeanty M.D.,Ph.D.
  2562.  
  2563.  
  2564.  
  2565.  
  2566.  
  2567.  
  2568.  
  2569.                                        39
  2570.  
  2571.  
  2572.  
  2573.  
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.    Patient: Foucher
  2581.  
  2582.  
  2583.                                Examination performed on  March 1, 1985.
  2584.  
  2585.                                                      Re: Foucher
  2586.                                                          Adele
  2587.                                                          28 years old
  2588.  
  2589.    To Dr Herodote
  2590.  
  2591.  
  2592.  
  2593.    Dear Dr Herodote,
  2594.  
  2595.  
  2596.         Thank you for referring to us Ms Foucher Adele  who is currently 25
  2597.    weeks by dates.
  2598.  
  2599.         The estimated gestational age is 25 weeks and 4 days, based on
  2600.    the BPD. The expected due date based on the LMP is June 13, 1985.
  2601.  
  2602.         The estimated fetal weight (EFW) is 677 grams (which is about 1
  2603.    pounds and  8 ounces).
  2604.  
  2605.         This baby looks great, it size and weight are appropriate for its
  2606.    age and no evidence of congenital malformations are seen. The fetal
  2607.    sex is that of a female.
  2608.  
  2609.         Sincerely yours,
  2610.  
  2611.  
  2612.  
  2613.  
  2614.                                        Vesalius
  2615.  
  2616.  
  2617.  
  2618.  
  2619.  
  2620.  
  2621.  
  2622.  
  2623.  
  2624.  
  2625.  
  2626.  
  2627.  
  2628.  
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639.  
  2640.  
  2641.